event-loop: make signalfd non-blocking
authorMarek Chalupa <mchqwerty@gmail.com>
Tue, 12 Aug 2014 09:35:06 +0000 (11:35 +0200)
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>
Mon, 18 Aug 2014 10:03:00 +0000 (13:03 +0300)
When we add more that one source to a signal, then wayland will
block in wl_event_loop_dispatch. This is due to the attampt to read
from signal's fd each time the source is dispatched.

  wl_event_loop_add_signal(loop, SIGINT, ...);
  wl_event_loop_add_signal(loop, SIGINT, ...);

  /* raise signal .. */

  /* we got two fd's ready, both for the one SIGINT */
  epoll_wait(...) = 2

  [ for (i == 0) ]
      source1->dispatch() --> read(fd1);
  [ for (i == 1) ]
      source2->dispatch() --> read(fd2); /* blocking! */

Reading from fd2 will block, because we got only one signal,
and it was read from fd1.

Signed-off-by: Marek Chalupa <mchqwerty@gmail.com>
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
src/event-loop.c

index 9790cde..a149db9 100644 (file)
@@ -233,7 +233,7 @@ wl_event_source_signal_dispatch(struct wl_event_source *source,
        int len;
 
        len = read(source->fd, &signal_info, sizeof signal_info);
-       if (len != sizeof signal_info)
+       if (!(len == -1 && errno == EAGAIN) && len != sizeof signal_info)
                /* Is there anything we can do here?  Will this ever happen? */
                wl_log("signalfd read error: %m\n");
 
@@ -263,7 +263,7 @@ wl_event_loop_add_signal(struct wl_event_loop *loop,
 
        sigemptyset(&mask);
        sigaddset(&mask, signal_number);
-       source->base.fd = signalfd(-1, &mask, SFD_CLOEXEC);
+       source->base.fd = signalfd(-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
        sigprocmask(SIG_BLOCK, &mask, NULL);
 
        source->func = func;