Repository navigation
comm::peek hangs #2841
Description
Activity
This seems to be even more serious than I thought: I rewrote my code to use select2 instead of peek and now the select2 is hanging...
Was able to work around this using task::spawn_sched:
// rustc --test multiple_tasks.rs && ./multiple_tasks use std; enum control_event { dup_event(str, comm::chan<str>), close_event, } // This works with single_threaded and with manual_threads(4|16). // Also tried thread_per_core and thread_per_task but they are not // implemented. fn silly2(n: uint) -> comm::chan<control_event> { let channel_port = comm::port(); let channel_channel = comm::chan(channel_port); do task::spawn_sched(task::manual_threads(4)) { let control_port: comm::port<control_event> = comm::port(); // this is bookkeeping that spawn_listener handles for us let control_channel = comm::chan(control_port); comm::send(channel_channel, control_channel); io::println(#fmt["started task %?", n]); loop { libc::funcs::posix88::unistd::sleep(1); if comm::peek(control_port) { alt comm::recv(control_port) { dup_event(data, data_ch) { io::println(#fmt["task %? received %?", n, data]); comm::send(data_ch, data + data); } close_event { io::println(#fmt["exiting task %?", n]); break; } } } } }; comm::recv(channel_port) } #[test] fn blah() { let po = comm::port(); let ch = comm::chan(po); let silly_channels = do vec::from_fn(10) |n| {silly2(n)}; for vec::each(silly_channels) |sc| { comm::send(sc, dup_event("hey", ch)); assert comm::recv(po) == "heyhey"; } for vec::each(silly_channels) |sc| { comm::send(sc, close_event); } }I suspect the call to
libc::funcs::posix88::unistd::sleep(1)might be part of the problem.sleepis outside of the realm of things the Rust scheduler is aware of, and so sleeping blocks a whole thread instead of allowing other tasks to run on that thread while the sleeping task is sleeping. I'd recommend usingstd::timer::sleep, which the Rust scheduler is aware of. That said,unistd::sleepshould wake up eventually, so I'm surprised this is hanging rather than just taking a potentially very long time to finish.Also,
recvblocks until data is available on a port, so sleeping in the loop isn't really necessary. It may be that you want to periodically perform some other processing though. If this is the case, I'd suggest usingstd::timer::recv_timeout.I don't think this behavior can be pinned on unistd::sleep (exclusively). Yesterday I saw the same symptom (task not starting up) and worked around it the same way (task::spawn_sched instead of task::spawn). There was a lot of code involved and a lot of tasks running around, but my code at least didn't call sleep.
(The code above was from some sample code of mine which used sleep in a rather unrealistic manner to keep the sample simple. My real code is where I saw this new task hang).
Found another place where tasks launched with spawn just hang: the test_server_client unit test in https://github.com/jdm/rust-socket on "Linux shell 3.2.0-24-generic #39-Ubuntu SMP Mon May 21 16:52:17 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux". Worked around again with spawn_sched.
Note that those unit tests did work on my Mac which is where I do 99% of my rust work.
Adding task::yield to comm::peek fixes the original case. I'm not sure about the select2 case. See pull request #2947.
The select2 case works for me. As a side note, I think there should be library sleep function that calls task::yield.
Nice work, @tedhorst. We don't currently insert yield checks on loop backedges like we should (#524), which means to loop around sleep and peek never yields. Adding a call to
task::yieldincomm::peekseems like kind of a hack, but I think it's reasonable for now given that we don't do yield checks like we should.This was fixed by #2947.
- added a commit that references this issue
on Apr 28, 2023 - added a commit that references this issue
on Jun 4, 2024 - added a commit that references this issue
on Apr 22, 2026
Was able to get comm::peek to hang with 8+ tasks. This was on Mac 10.7.4 using a rust pulled on July 8, 2012.
Here is a test case: