Question

Iam looking to write a socket program based on libev. I noticed that several examples as stated in https://github.com/coolaj86/libev-examples/blob/master/src/unix-echo-server.c use the call backs based on init. For example,

main() {

......
ev_io_init(&client.io, client_cb, client.fd, EV_READ|EV_WRITE);
ev_io_start(EV_A_ &server.io);

}

static void client_cb (EV_P_ ev_io *w, int revents)
{
  if (revents & EV_READ)
  {
      ....
  } else if (revents & EV_WRITE) {

     ......
  }
}

My question comes from the expected behaviour, say for example, all that i read when in EV_READ is stored in a linked list. Lets say I keep getting free flow of packets to read, will i ever get a chance to get into EV_WRITE? I have to send out all that I recv through read to another socket. So Will it be once EV_READ and second time EV_WRITE? In other words when will EV_WRITE be unblocked? Or do I need to block EV_READ for EV_WRITE to be called. Can someone help me understand this?

Was it helpful?

Solution

To answer shortly: If you allways check for one type of event first and then have an else if for the other you risk starvation. In general I would check for both, unless the specified protocol made it impossible for both to be activated at the same time.

Here is a more iffy answer: The link in your question does not contain a code structure such as your question. The client https://github.com/coolaj86/libev-examples/blob/master/src/unix-echo-client.c does have a similar callback. You will notice it disables write events, when it has written once.

// once the data is sent, stop notifications that
// data can be sent until there is actually more
// data to send
ev_io_stop(EV_A_ &send_w);
ev_io_set(&send_w, remote_fd, EV_READ);
ev_io_start(EV_A_ &send_w);

That looks like an attempt to avoid starvation of the pipe READ event branch. Even though Im not very familiar with libev, the github examples you linked to do not seem very robust. E.g static void stdin_cb (EV_P_ ev_io *w, int revents)does not use the return value of getline() to detect EOF. Also the send() and recv() socket operation return values are not inspected for how much was read or written (though on local named pipe streams the amounts will most likely match the amounts that were requested). If this was later changed to a TCP based connection, checking the amounts would be vital.

OTHER TIPS

I think you should keep write callback separated from read callback:

main() {
    ev_io_init(&read.io, read_cb, client.fd, EV_READ);
    ev_io_init(&write.io, writead_cb, client.fd, EV_WRITE);
    ev_io_start(EV_A_ &read.io);
    ev_io_start(EV_A_ &write.io);
}

This is my solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top