I need to read data provided by an external process via a posix filedescriptor in my Rust program. The fd connection is kept up a very long time (hours) and the other side passes data to me from time to time. So I need to read and process the data stream continuously.
To do so, I wrote a loop that calls libc::read()
(readv actually) to read the data and processes it when received. Since this would block the whole scheduler, I'm spawning a task on a new scheduler (task::spawn_sched(SingleThreaded)
). This works fine as long as it runs, but I just can't find a way to cleanly shut down the loop.
Since the loop is blocking most of the time, I can't use a port/chan to notify the loop to exit.
I tried to kill the loop task by taking it down using a failing linked task (spawn the loop task supervised, spawn a linked task within it and wait for a signal on a port to happen before fail!()
ing and taking down the loop task with it). It works well in tests, but the libc::read()
isn't interrupted (the task doesn't fail before read finishes and it hits task::yield()
at some time.
I learned a lot looking at libcore sources, but I can't seem to find a proper solution.
- Is there a way to kill a (child) task in Rust even if it's doing some long external function call like a blocking read?
- Is there a way to do nonblocking reads on a posix filedescriptor so that Rust keeps control over the task?
- How can I react to signals, e.g. SIGTERM if the user terminates my program. There doesn't seem to be something like
sigaction()
in Rust yet?
mozilla/rust/pull/11410
, see also my other issue report for rust-zmqerickt/rust-zmq/issues/24
which also depends on this. (sorry about the links)