Skip to content
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

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

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

Comments

Projects
None yet
6 participants
@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

This comment has been minimized.

Copy link
Member

alexcrichton commented Jan 23, 2016

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

@vi

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

Copy link
Contributor Author

vi commented Jan 23, 2016

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Jan 25, 2016

@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

This comment has been minimized.

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

This comment has been minimized.

Copy link
Member

alexcrichton commented Jan 25, 2016

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

Copy link
Member

alexcrichton commented Jan 26, 2016

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

This comment has been minimized.

Copy link
Member

alexcrichton commented Jan 26, 2016

triage: I-nominated

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Jan 26, 2016

also just cc @rust-lang/compiler

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jan 26, 2016

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

@dotdash

This comment has been minimized.

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

This comment has been minimized.

Copy link
Member

alexcrichton commented Jan 26, 2016

@nikomatsakis oh right sorry, I should have clarified there

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

@pnkfelix

This comment has been minimized.

Copy link
Member

pnkfelix commented Jan 26, 2016

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

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jan 28, 2016

triage: P-high

@rust-highfive rust-highfive added P-high 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

Fix truncated drop pattern on 32bit -> 64bit cross compilation
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

dotdash added a commit to dotdash/rust that referenced this issue Jan 29, 2016

Fix truncated drop pattern on 32bit -> 64bit cross compilation
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

Auto merge of #31283 - dotdash:32_64_cc, r=alexcrichton
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

@bors bors closed this in #31283 Jan 29, 2016

rthomas added a commit to rthomas/rust that referenced this issue Feb 1, 2016

Fix truncated drop pattern on 32bit -> 64bit cross compilation
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.