How to handle blocking i/o in Rust, or long runnin

2019-03-15 00:13发布

问题:

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.

  1. 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?
  2. Is there a way to do nonblocking reads on a posix filedescriptor so that Rust keeps control over the task?
  3. 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?

回答1:

  1. According to mozila, killing a task is no more possible, for now, let alone blocking read.
  2. It will be possible to do so after mozilla/rust/pull/11410, see also my other issue report for rust-zmq erickt/rust-zmq/issues/24 which also depends on this. (sorry about the links)
  3. Maybe the signal listener will work for you.


标签: io task ffi rust