Folks,
I am following up on this: Debugging closed channel and ManuallyDrop
Quick recap.
A rust structure that contains a sender:
struct DBKey {
tx: Sender<Stuff>
... other_stuff ...
}
The structure is allocated through Box, let dbkey = Box::new(dbkey)
.
We get a raw pointer let ptr = Box::into_raw(dbkey)
.
We pass the pointer to a C function that store it somewhere we are not concerned with.
Later, eventually, we do the trip back.
We ask to a C function the value of that pointer, let ptr = ffi::something();
We read it back let dbkey = ptr.read()
(it is a problem if i use std::mem::read()
instead of Box::from_raw()
in this case?) .
And we clone the sender return Ok(dbkey.tx.clone()
.
The first time I clone the sender everything works fine. However, the second time it panics with:
thread '<unnamed>' panicked at 'upgrading again', src/libstd/sync/mpsc/oneshot.rs:203:22
stack backtrace:
0: 0x7f432bf4d104 - backtrace::backtrace::libunwind::trace::heb43798aede8bd30
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
1: 0x7f432bf4d104 - backtrace::backtrace::trace_unsynchronized::had2ba7dec4bd2732
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
2: 0x7f432bf4d104 - std::sys_common::backtrace::_print_fmt::hda61f46e822731b2
at src/libstd/sys_common/backtrace.rs:84
3: 0x7f432bf4d104 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hfe37fa5de6572965
at src/libstd/sys_common/backtrace.rs:61
4: 0x7f432bf6ae8c - core::fmt::write::h74887d18db27282c
at src/libcore/fmt/mod.rs:1025
5: 0x7f432bf4b497 - std::io::Write::write_fmt::h6808f3d5eceed5e5
at src/libstd/io/mod.rs:1426
6: 0x7f432bf4f07e - std::sys_common::backtrace::_print::hcc0fd4b3552039ef
at src/libstd/sys_common/backtrace.rs:65
7: 0x7f432bf4f07e - std::sys_common::backtrace::print::h1c9c5c1c0505592d
at src/libstd/sys_common/backtrace.rs:50
8: 0x7f432bf4f07e - std::panicking::default_hook::{{closure}}::hefb6085c1ab83a59
at src/libstd/panicking.rs:193
9: 0x7f432bf4ed71 - std::panicking::default_hook::h1b037d2bf0657ab3
at src/libstd/panicking.rs:210
10: 0x7f432bf4f73b - std::panicking::rust_panic_with_hook::h787d7f532b084b9a
at src/libstd/panicking.rs:471
11: 0x7f432bf403f7 - std::panicking::begin_panic::h0269c2ebc1ade1c9
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/panicking.rs:404
12: 0x7f432bf2c30a - std::sync::mpsc::oneshot::Packet<T>::upgrade::h4f0412a5aacef7bb
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/macros.rs:16
13: 0x7f432bde6647 - <std::sync::mpsc::Sender<T> as core::clone::Clone>::clone::h3c925c50b0e8ef72
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/sync/mpsc/mod.rs:856
14: 0x7f432bdc48be - <redisql_lib::redis::NoisyDrop<T> as core::clone::Clone>::clone::hb22cefbfadf74dc4
at redisql_lib/src/redis.rs:1537
15: 0x7f432be054aa - redisql_lib::redis::RedisKey::get_channel::h0d42630b8b3af33d
at redisql_lib/src/redis.rs:534
16: 0x7f432bc97cc7 - redis_sql::v2::exec::do_exec_v2::h3522247cf6d4c905
at src/v2/exec.rs:118
17: 0x7f432bc9561f - redis_sql::v2::exec::Exec_v2::h32953ca646b11ea5
at src/v2/exec.rs:37
18: 0x55e632531128 - RedisModuleCommandDispatcher
at /home/smosciat/redis-stable/src/module.c:542
19: 0x55e6324bcdc5 - call
at /home/smosciat/redis-stable/src/server.c:2439
20: 0x55e6324bd4cf - processCommand
at /home/smosciat/redis-stable/src/server.c:2733
21: 0x55e6324cdfb1 - processInputBuffer
at /home/smosciat/redis-stable/src/networking.c:1470
22: 0x55e6324b6800 - aeProcessEvents
at /home/smosciat/redis-stable/src/ae.c:443
23: 0x55e6324b6beb - aeMain
at /home/smosciat/redis-stable/src/ae.c:501
24: 0x55e6324b3794 - main
at /home/smosciat/redis-stable/src/server.c:4200
25: 0x7f432ed5bb97 - __libc_start_main
26: 0x55e6324b39ea - _start
27: 0x0 - <unknown>
fatal runtime error: failed to initiate panic, error 5
I follow a little bit the implementation details of channels and it turns out that channels are implemented differently if you have already send something through them or not, and if you have invoked clone or not.
So I tried another experiment. Before to transform the DBKey to a pointer, so completely in the Rust domain, I tried to clone the channel once and to send a value through it.
Doing so, the panic does not happen anymore and the code works as expected.
The question now is, am I broking some invariant? It is some sort of bug in the channel implementation? Should I report it to somebody? Should I try to reproduce it somehow in the playground?