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

Assertion failure when locking a mutex in a c thread (linux) #17485

Closed
blastrock opened this issue Sep 23, 2014 · 9 comments
Closed

Assertion failure when locking a mutex in a c thread (linux) #17485

blastrock opened this issue Sep 23, 2014 · 9 comments

Comments

@blastrock
Copy link

Hi,

I get an assertion failure when I try to lock a mutex from a thread created from C++ (I think it is reproducible with c). I made a minimal example here: https://github.com/blastrock/rustcrash

Uncompress the archive and type "make run". On my machine it finishes with:

fatal runtime error:  assertion failed: !ptr.is_null()
Illegal instruction 

EDIT: Here is the stack trace:

(gdb) bt
#0  0x00005555555c39c5 in util::abort::hf673a6fea37897c4eEa ()
#1  0x00005555555bff79 in local_ptr::compiled::take::h12674065722481156391 ()
#2  0x00005555555c3006 in lock::failing::h8c52553afcb2a61cC7e ()
#3  0x00005555555c326a in lock::PoisonOnFail$LT$$x27a$GT$::new::hcfbb39080c770903y9e ()
#4  0x000055555555c37e in lock::Mutex$LT$T$GT$::lock::h9394655342227765001 ()
#5  0x000055555555c21b in callback::__rust_abi ()
#6  0x000055555555c1a3 in callback::h9d49d629a3b51de4faa ()
#7  0x00007ffff7bd8238 in trigger_callback () from ./liblib.so
#8  0x00007ffff7bd9699 in void std::_Bind_simple<void (*())()>::_M_invoke<>(std::_Index_tuple<>) () from ./liblib.so
#9  0x00007ffff7bd95e1 in std::_Bind_simple<void (*())()>::operator()() () from ./liblib.so
#10 0x00007ffff7bd955e in std::thread::_Impl<std::_Bind_simple<void (*())()> >::_M_run() () from ./liblib.so
#11 0x00007ffff6c9b8a0 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#12 0x00007ffff77b70a4 in start_thread (arg=0x7ffff5fff700) at pthread_create.c:309
#13 0x00007ffff72d6c2d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
@killerswan
Copy link
Contributor

I can't open your file. Can you put the code in a GitHub repo instead so I can browse it and clone it?

@blastrock
Copy link
Author

Good idea! Sorry, I didn't think of that. Anyway, here it is: https://github.com/blastrock/rustcrash

@blastrock
Copy link
Author

I think I found it. It comes down to a thread-local variable not being initialized. It is located in librustrt/local_ptr.rs:

    #[thread_local]
    pub static mut RT_TLS_PTR: *mut u8 = 0 as *mut u8;

This variable should be initialized by Task, but since we come from a c context, there is no such Task.

I think that I was wrong using a Mutex here since they may pause threads and schedule another task over it, which is not what we want when we come from a c context (which may have locked native mutexes or rely on thread-local storage).

My code seems to work if I use std::rt::mutex::NativeMutex. If this is the way to go, maybe this documentation should be updated: http://doc.rust-lang.org/guide-ffi.html#asynchronous-callbacks and the error message should be made more explicit.

@thestinger
Copy link
Contributor

This is working as designed. It's undefined behaviour to call libstd on threads created outside of the libstd API. You need to use #![no_std] to write a library with a normal C API in Rust. Exposing more functionality without this requirement is a work-in-progress.

@blastrock
Copy link
Author

I'm not writing a library with a C API, I'm just using a C library. In the documentation link I provided, it is said that it is possible (and I managed to do it with either NativeMutexes or channels). If it is not officially possible, then the documentation should say it.

@thestinger
Copy link
Contributor

You're running code from the standard library on a thread it didn't create without manually initializing the runtime on it. That's explicitly not permitted and it is documented.

@blastrock
Copy link
Author

Maybe you're right, but I can't find that part in the documentation. What I did read is

Things get more complicated when the external library spawns its own threads and invokes callbacks from there. In these cases access to Rust data structures inside the callbacks is especially unsafe and proper synchronization mechanisms must be used. Besides classical synchronization mechanisms like mutexes, one possibility in Rust is to use channels (in std::comm) to forward data from the C thread that invoked the callback into a Rust task.

@thestinger
Copy link
Contributor

You're free to file bugs about inaccurate parts of the documentation, but the undefined behaviour you're getting is not a bug and is documented elsewhere.

@thestinger
Copy link
Contributor

Using Rust in a C callback with the standard library implies the following:

  • the code must run on a thread created by Rust
  • the code must catch exceptions thrown by Rust and either translate to an error for the C library or abort

Anything else has undefined behaviour.

lnicola pushed a commit to lnicola/rust that referenced this issue Jul 11, 2024
…=alibektas

minor : Fix duplicate snippets showing up on hover.

With each `config::apply_change` duplicate configs were being added.
Now we first drain the vec that holds these and then start adding. This fixes rust-lang#17485
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants