code
code copied to clipboard
ch12-sjlj Why the program not execute the line `println!("early return!");`, set_jmp and long_jmp didn`t work.
To provide a bit more context, at least as of 2023-01-14, Rust Nightly produces code that just crashes (Segementation Fault), instead of succeeding with the setjmp()
/ longjmp()
trickery, in the ch12/ch12-sjlj
example.
I'm not that surprised. Even in C setjmp()
/ longjmp()
are wildly unsafe C library calls, that it's recomended never to use unless you have absolutely no other choice. And preferably you wouldn't be longjmp()
ing from a signal handler back to other (non-signal handler) code, as is implemented here. FWIW, the idea of trying to setjmp()
/longjmp()
via a foreign function interface (ie, Rust to C) struck me as very unlikely to succeed; I guess there was maybe a rust compiler Nightly version/LLDB version where what was implemented happened to work, but it seems extremely fragile.
From a bit of debugging it is unsurprisingly crashing in the longjmp()
call. And the fact that trying to read the franken_pointer
value reports it couldn't read from address 0x18
strongly implies that's an offset from a NULL pointer. Presumably only the liberal use of unsafe
here is preventing the compiler from saying "What? No, just no" to this :-)
(FTR, it looks like RETURN_HERE
-- the jump buffer -- does have a valid address, and might even have plausible contents -- although there's a lot of 0 bytes in it.)
Ewen
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ rustc +nightly --version
rustc 1.68.0-nightly (0b90256ad 2023-01-13)
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ cargo +nightly --version
cargo 1.68.0-nightly (d992ab4e9 2023-01-10)
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ cargo +nightly clean
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ cargo +nightly run
Compiling libc v0.2.84
Compiling ch10-sjlj v0.1.0 (/home/ewen/misc/src/rust/rust-in-action/ch12/ch12-sjlj)
Finished dev [unoptimized + debuginfo] target(s) in 1.04s
Running `target/debug/ch10-sjlj`
#
##
###
Segmentation fault (core dumped)
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ nl -ba src/main.rs | awk '$1 > 32 && $1 < 36 {print;}'
33 let franken_pointer = ptr_to_jmp_buf();
34 unsafe { longjmp(franken_pointer) }; // <5>
35 }
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$
Example core dump back trace
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ rust-lldb target/debug/ch10-sjlj -c $(ls -t /var/lib/apport/coredump/core.* | head -1)
(lldb) command script import "/home/ewen/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/etc/lldb_lookup.py"
(lldb) command source -s 0 '/home/ewen/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/etc/lldb_commands'
Executing commands in '/home/ewen/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/etc/lldb_commands'.
(lldb) type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?str$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?\\[.+\\]$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)BTreeSet<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)BTreeMap<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)Ref<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)RefMut<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)RefCell<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^core::num::([a-z_]+::)*NonZero.+$" --category Rust
(lldb) type category enable Rust
(lldb) target create "target/debug/ch10-sjlj" --core "/var/lib/apport/coredump/core._home_ewen_misc_src_rust_rust-in-action_ch12_ch12-sjlj_target_debug_ch10-sjlj.1000.815c6d8a-8ee6-45a1-b111-d05f4b76a7db.30059.26038095"
Core file '/var/lib/apport/coredump/core._home_ewen_misc_src_rust_rust-in-action_ch12_ch12-sjlj_target_debug_ch10-sjlj.1000.815c6d8a-8ee6-45a1-b111-d05f4b76a7db.30059.26038095' (x86_64) was loaded.
(lldb) bt
* thread #1, name = 'ch10-sjlj', stop reason = signal SIGSEGV
* frame #0: 0x00005582c7a92a81 ch10-sjlj`ch10_sjlj::return_early::h9f631bb2eb221bac at main.rs:34:12
(lldb) p franken_pointer
error: Couldn't materialize: couldn't get the value of variable franken_pointer: read memory from 0x18 failed (0 of 8 bytes read)
error: errored out in DoExecute, couldn't PrepareToExecuteJITExpression
(lldb) print &RETURN_HERE
(char (*)[64]) $2 = 0x00005582c7ada032
(lldb) print sizeof(RETURN_HERE)
(unsigned long) $3 = 64
(lldb) print RETURN_HERE
(char[64]) $4 = "\0\0\0\0\0\0\0\0\x84-\xa9ǂU\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
(lldb)
Just remove attributes {#[link_name...]) of setjmp and longjmp signatures.