Skip to content

In cross-compiled i686->x86_64 code, thread::spawn crashes on my system #31139

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vi opened this issue Jan 23, 2016 · 18 comments
Closed

In cross-compiled i686->x86_64 code, thread::spawn crashes on my system #31139

vi opened this issue Jan 23, 2016 · 18 comments
Assignees
Labels
P-high High priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@vi
Copy link
Contributor

vi commented Jan 23, 2016

Session:

$ cat t.rs 
use std::thread;

fn main() {
    println!("A");
    thread::spawn(|| {
        println!("B");
    });
}
$ rustc --version
rustc 1.8.0-nightly (18b851bc5 2016-01-22)
$ file `which rustc`
/home/vi/home/rust/prefix/bin/rustc: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.9, not stripped
$ rustc -g t.rs 
$ ./t
A
$ rustc -g t.rs --target x86_64-unknown-linux-musl
$ ./t
A
Segmentation fault
$ rustc -g t.rs --target x86_64-unknown-linux-gnu
$ ./t
A
Segmentation fault
$ /n/gdb -args ./t
.....
(gdb) run
Starting program: /home/vi/code/scgi_uploader/t 
warning: the debug information found in "/lib64/ld-2.19.so" does not match "/lib64/ld-linux-x86-64.so.2" (CRC mismatch).

warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?
(more gdb warnings skipped)
A

Program received signal SIGSEGV, Segmentation fault.
0x000055555555a704 in core..option..Option$LT$core..result..Result$LT$$LP$$RP$$C$$u20$Box$LT$core..any..Any$u20$$u2b$$u20$Send$u20$$u2b$$u20$$u27$static$GT$$GT$$GT$::drop.4127::hb088075983aead08 ()
(gdb) bt
#0  0x000055555555a704 in core..option..Option$LT$core..result..Result$LT$$LP$$RP$$C$$u20$Box$LT$core..any..Any$u20$$u2b$$u20$Send$u20$$u2b$$u20$$u27$static$GT$$GT$$GT$::drop.4127::hb088075983aead08 ()
#1  0x000055555555a6f6 in core..cell..UnsafeCell$LT$core..option..Option$LT$core..result..Result$LT$$LP$$RP$$C$$u20$Box$LT$core..any..Any$u20$$u2b$$u20$Send$u20$$u2b$$u20$$u27$static$GT$$GT$$GT$$GT$::drop.4124::ha81422590a6ae76a ()
#2  0x000055555555b67a in alloc..arc..ArcInner$LT$core..cell..UnsafeCell$LT$core..option..Option$LT$core..result..Result$LT$$LP$$RP$$C$$u20$Box$LT$core..any..Any$u20$$u2b$$u20$Send$u20$$u2b$$u20$$u27$static$GT$$GT$$GT$$GT$$GT$::drop.4628::hdc113cdfe383d7c6 ()
#3  0x000055555555b64c in Box$LT$alloc..arc..ArcInner$LT$core..cell..UnsafeCell$LT$core..option..Option$LT$core..result..Result$LT$$LP$$RP$$C$$u20$Box$LT$core..any..Any$u20$$u2b$$u20$Send$u20$$u2b$$u20$$u27$static$GT$$GT$$GT$$GT$$GT$$GT$::drop.4625::hf63444c339d7dc5e ()
#4  0x000055555555b61c in t::boxed::Box<T>::into_raw (b=0x1d1d1d1d1d1d1d1d) at ../src/liballoc/boxed.rs:275
#5  0x000055555555b477 in t::arc::Arc<T>::new (data=...) at ../src/liballoc/arc.rs:201
#6  0x000055555555abb2 in t::thread::Builder::spawn<closure,()> (self=..., f=...) at ../src/libstd/thread/mod.rs:265
#7  0x000055555555921c in t::thread::spawn<closure,()> (f=...) at ../src/libstd/thread/mod.rs:317
#8  0x0000555555559185 in t::main () at t.rs:5
#9  0x0000555555566195 in sys_common::unwind::try::try_fn::h4949629795001311128 ()
#10 0x0000555555563ca9 in __rust_try ()
#11 0x0000555555565e21 in rt::lang_start::he0f87e5fa36aecbfywy ()
#12 0x000055555555bf9a in main ()
Warning: the current language does not match this frame.
(gdb) q
...
Quit anyway? (y or n) y
$ apt-cache policy libc6 libc6:amd64 | grep -F '***'
 *** 2.19-18+deb8u1 0
 *** 2.19-18+deb8u1 0
$ ed t.rs 
105
1i
#![feature(alloc_system)]
extern crate alloc_system;
.
wq
158
$ rustc -C linker=~rust/gccwrapper -g t.rs --target i686-pc-windows-gnu
$ wine t.exe 
A
@vi vi changed the title In cross-compiled code, thread::spawn crashes on my system In cross-compiled i686->x86_64 code, thread::spawn crashes on my system Jan 23, 2016
@alexcrichton
Copy link
Member

Is there a way that this could be reproduced locally? Either through a VM or perhaps a docker container?

@vi
Copy link
Contributor Author

vi commented Jan 23, 2016

What shall be in the VM? Just a minimal system to reproduce the crash itself or also full Rust toolchain?

@vi
Copy link
Contributor Author

vi commented Jan 23, 2016

  1. Downloaded debian image from here
  2. Created additional 1GB partition for Rust, formatted ext4.
  3. qemu-system-i386 -enable-kvm -m 2000 -hda debian_wheezy_i386_standard.qcow2
  4. apt-get update, apt-get install linux-image-amd64
  5. qemu-system-x86_64 -m 2000 -enable-kvm -hda debian_wheezy_i386_standard.qcow2 -hdb rust
  6. mounted /dev/sdb to /mnt
  7. wget http://static.rust-lang.org/rustup.sh (https fails)
  8. ./rustup.sh --prefix /mnt/prefix --channel nightly
  9. Got stopped by unavailable sudo again, two times in two days...
  10. ./rustup.sh --prefix /mnt/prefix --channel nightly --disable-sudo --save -y
  11. Realized that it it installed stable Rust, and not where I asked. OK, continuing anyway. Separate partition is not needed actually.
  12. apt-get install libc6, dpkg --add-architecture amd64, apt-get update, apt-get install libc6:amd64 gcc gcc-4.7-multilib
  13. Installed http://static.rust-lang.org/dist/rust-std-nightly-x86_64-unknown-linux-gnu.tar.gz
  14. Realized that it's not a nightly because of point 11 and installed http://static.rust-lang.org/dist/rust-std-1.6.0-x86_64-unknown-linux-gnu.tar.gz
  15. Tried building and running t.rs without --target - works.
  16. Tried --target=x86_64-unknown-linux-gnu - crash.

You can try yourself by downloading the qcow2 image. Select amd64 kernel in grub, use root:root to login. I'll add the link soonish.

@vi
Copy link
Contributor Author

vi commented Jan 23, 2016

Link to the VM image (not sure if the link will actually download): magnet:?xt=urn:btih:e0493de828e6a0b569c26d66190844f76c899f0c&tr=http%3A%2F%2Ftracker.nl-2000.com%3A6969%2Fannounce%00

@vi
Copy link
Contributor Author

vi commented Jan 23, 2016

Alternative easier link: http://vi-server.org/pub/debian_wheezy_i386+amd64_rust.qcow2

@alexcrichton
Copy link
Member

@vi your linked donwloaded ok but I unfortunately can't seem to reproduce just yet, I'm getting:

root@debian-i386:~# ./t                 
-bash: ./t: cannot execute binary file  

Is there a special way that qemu needs to be invoked or is there something else going on?

@vi
Copy link
Contributor Author

vi commented Jan 25, 2016

Select amd64 kernel in grub

Have you did this? It's not default. There is GRUB menu at start of the VM.

@alexcrichton
Copy link
Member

Hm no, I only have a -curses interface unfortunately and that doesn't seem to be available through that. I'll try to have to see what I can do at a later date

@vi
Copy link
Contributor Author

vi commented Jan 25, 2016

You can make amd64 kernel to boot by default.

  1. vi /etc/default/grub
  2. Set GRUB_DEFAULT="2"
  3. Save the file, leave the editor
  4. update-grub
  5. reboot

@vi
Copy link
Contributor Author

vi commented Jan 26, 2016

You can also update the image (I performed and uploaded those changes):

rsync://vi-server.org/pub/debian_wheezy_i386+amd64_rust.qcow2

@alexcrichton
Copy link
Member

cc @pnkfelix, this looks like a bug in dropck maybe? This is reproducible (on linux) via:

os=unknown-linux-gnu                                                         
target=x86_64-$os                                                            
host=i686-$os                                                                
curl https://static.rust-lang.org/dist/rustc-nightly-$host.tar.gz | tar xzf -
./rustc-nightly-$host/install.sh --prefix=install           
curl https://static.rust-lang.org/dist/rust-std-nightly-$target.tar.gz | \   
  tar xzf - --strip-components=4 -C install/lib/rustlib \                    
  rust-std-nightly-$target/rust-std-$target/lib/rustlib                      

echo 'fn main() { std::thread::spawn(|| {}).join().unwrap(); }' |            
  PATH=`pwd`/install/bin:$PATH \                                             
  LD_LIBRARY_PATH=`pwd`/install/lib \                                        
  rustc - -o foo --target $target                                            
./foo                                                                        

It looks like this is a bug with any 32->64 compilation, and at least on Linux for me the faulting instruction is:

$ gdb ./foo
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./foo...done.
(gdb) r
Starting program: /home/alex/code/wut/wut/rustc-nightly-i686-unknown-linux-gnu/rustc/foo 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x000055555555b324 in core..option..Option$LT$core..result..Result$LT$$LP$$RP$$C$$u20$Box$LT$core..any..Any$u20$$u2b$$u20$Send$u20$$u2b$$u20$$u27$static$GT$$GT$$GT$::drop.3726::hc2f93767862c1e08 ()
(gdb) disas
Dump of assembler code for function _ZN142core..option..Option$LT$core..result..Result$LT$$LP$$RP$$C$$u20$Box$LT$core..any..Any$u20$$u2b$$u20$Send$u20$$u2b$$u20$$u27$static$GT$$GT$$GT$9drop.372617hc2f93767862c1e08E:
   0x000055555555b320 <+0>:     sub    $0x18,%rsp
=> 0x000055555555b324 <+4>:     mov    (%rdi),%rax
   0x000055555555b327 <+7>:     test   %rax,%rax
   0x000055555555b32a <+10>:    mov    %rdi,0x10(%rsp)
   0x000055555555b32f <+15>:    mov    %rax,0x8(%rsp)
(gdb) print/x $rdi
$1 = 0x1d1d1d1d1d1d1d2d

Seems suspicious!

@alexcrichton alexcrichton added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jan 26, 2016
@alexcrichton
Copy link
Member

triage: I-nominated

@alexcrichton
Copy link
Member

also just cc @rust-lang/compiler

@nikomatsakis
Copy link
Contributor

By dropck, I guess you mean a potential buy in the translation of drops?

@dotdash
Copy link
Contributor

dotdash commented Jan 26, 2016

dtor_done_usize returns usize, so the drop flag gets truncated in this setup, as usize is only 32bits.

@pnkfelix pnkfelix self-assigned this Jan 26, 2016
@alexcrichton
Copy link
Member

@nikomatsakis oh right sorry, I should have clarified there

@dotdash that sounds like it'd do the trick!

@pnkfelix
Copy link
Member

ah yeah I hadn't imagined someone cross-compiling to x64 from i686. Total oversight in my part on making that API.

@nikomatsakis
Copy link
Contributor

triage: P-high

@rust-highfive rust-highfive added P-high High priority and removed I-nominated labels Jan 28, 2016
@dotdash dotdash assigned dotdash and unassigned pnkfelix Jan 29, 2016
dotdash added a commit to dotdash/rust that referenced this issue Jan 29, 2016
When cross compiling for a target that has a larger usize type than the
host system, we use a truncated value to mark data as dropped,
eventually leading to drop calls on already dropped data. To properly
handle this, the drop pattern needs to be of type u64.

Since C_integral truncates its given value to the requested size anyway,
we can also drop the function that chose between the u32 and u64 values,
and always use the u64 constant.

Fixes rust-lang#31139
bors added a commit that referenced this issue Jan 29, 2016
When cross compiling for a target that has a larger usize type than the
host system, we use a truncated value to mark data as dropped,
eventually leading to drop calls on already dropped data. To properly
handle this, the drop pattern needs to be of type u64.

Since C_integral truncates its given value to the requested size anyway,
we can also drop the function that chose between the u32 and u64 values,
and always use the u64 constant.

Fixes #31139

r? @pnkfelix
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P-high High priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants