Hi

While working on suspend/resume on my embedded system I ran into to the
race problem between select and signals. See this link for a description
of the problem:

http://www.xs4all.nl/~evbergen/unix-signals.html

The problem is that the following code in ecore_main_select is not an
atomic operation and could end up in select waiting forever even though
there is a signal to be served and put in the event queue:

   if (_ecore_signal_count_get()) return -1;
   ret = select(max_fd + 1, &rfds, &wfds, &exfds, t);

My proposed solution (see attached patch) is something similar to that
described in above link, namely to create a pipe to flag a signal
arrival to select. NOTE: the attached patch currently only handles
sigusr1 and sigusr2 and has almost no error checking.

As far as I can tell, the attached patch still have a race around
sig_count and sigXXX_count. I thought about adding the signal number to
the signal pipe to avoid this race, but that solution could result in
pipe buffer overflow and then signals would get lost.

Before I continue working on this patch, I really like your comments and
suggestions.

Thanks

-- Lars Munch

Index: src/lib/ecore/ecore_signal.c
===================================================================
RCS file: /var/cvs/e/e17/libs/ecore/src/lib/ecore/ecore_signal.c,v
retrieving revision 1.35
diff -u -r1.35 ecore_signal.c
--- src/lib/ecore/ecore_signal.c	26 Aug 2007 11:17:21 -0000	1.35
+++ src/lib/ecore/ecore_signal.c	23 Jan 2008 15:53:28 -0000
@@ -60,6 +60,9 @@
 static volatile siginfo_t *sigrt_info = NULL;
 #endif
 
+static int               pipe_fd[2];
+static Ecore_Fd_Handler *pipe_handler;
+
 void
 _ecore_signal_shutdown(void)
 {
@@ -110,13 +113,52 @@
 #endif
 }
 
+static void
+_ecore_signal_pipe_fd_flag()
+{
+   int count;
+   char f = 1;
+
+   /* Empty signal pipe completely */
+   for(count = 0; read(pipe_fd[0], &f, sizeof(f)) > 0; count++) ;
+
+   /* Put one flag into signal pipe */
+   write(pipe_fd[1], &f, sizeof(f));
+}
+
+static int
+_ecore_signal_pipe_fb_callback(void *data, Ecore_Fd_Handler *fdh)
+{
+   int count;
+   char f;
+
+   /* Empty signal pipe completely */
+   for(count = 0; read(fdh->fd, &f, sizeof(f)) > 0; count++) ;
+   
+   if(count)
+      _ecore_signal_call();
+   
+   return 1;
+}
+
 void
 _ecore_signal_init(void)
 {
+   int ret;
 #ifdef SIGRTMIN
    int i, num = SIGRTMAX - SIGRTMIN;
 #endif
 
+   ret = pipe(pipe_fd);
+   assert(!ret);
+
+   fcntl(pipe_fd[0], F_SETFL, O_NONBLOCK);
+   fcntl(pipe_fd[1], F_SETFL, O_NONBLOCK);
+
+   pipe_handler = ecore_main_fd_handler_add(pipe_fd[0], ECORE_FD_READ,
+					    _ecore_signal_pipe_fb_callback,
+					    NULL, NULL, NULL);
+
    _ecore_signal_callback_set(SIGPIPE, _ecore_signal_callback_ignore);
    _ecore_signal_callback_set(SIGALRM, _ecore_signal_callback_ignore);
    _ecore_signal_callback_set(SIGCHLD, _ecore_signal_callback_sigchld);
@@ -401,6 +443,8 @@
    else
      sigusr1_info.si_signo = 0;
 
+   _ecore_signal_pipe_fd_flag();
+
    sigusr1_count++;
    sig_count++;
 }
@@ -413,6 +457,8 @@
    else
      sigusr2_info.si_signo = 0;
 
+   _ecore_signal_pipe_fd_flag();
+
    sigusr2_count++;
    sig_count++;
 }
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to