I've found and fixed another bug related to signal handling - sigcx's
non-GTK library doesn't handle select() bailing due to EINTR, and
generates spurious file events as a result.  This is patch-6 in my arch
branch, the following diff as attached, and I've updated the pretend-NMU
to -2.4 which contains it.

Fix interruption of select() by a signal causing spurrious file events.

The select() loop wasn't being restarted on EINTR, wrap it in such a loop.
Previously, it'd cause a fall-through into attempting to read fd sets
that hadn't been initialized, and would generate spurrious file events as a
result.

- Steven Brown <[EMAIL PROTECTED]>


--- orig/sigcx/dispatch.cc
+++ mod/sigcx/dispatch.cc
@@ -357,31 +357,36 @@
     fd_set wr = wr_fds_;
     fd_set ex = ex_fds_;
     
-    if (tm_events_.size() == 0)
+    // Loop on select, restarting if we were interrupted by a signal.
+    int result;
+    do
     {
-      UnGuard unguard (mutex_);
-      int result = select(FD_SETSIZE, &rd, &wr, &ex, 0);
-      assert(result != -1 || errno == EINTR);
-    }
-    else
-    {
-      now.get_current_time();
-      timeout = tm_events_.begin()->first.expiration - now;
+      if (tm_events_.size() == 0)
+      {
+        UnGuard unguard (mutex_);
+        result = select(FD_SETSIZE, &rd, &wr, &ex, 0);
+        assert(result != -1 || errno == EINTR);
+      }
+      else
+      {
+        now.get_current_time();
+        timeout = tm_events_.begin()->first.expiration - now;
 
-      UnGuard unguard(mutex_);
-      
-      if (timeout < TimeVal(0))
-        timeout = TimeVal(0);
-      
-      struct timeval tv;
-      tv.tv_sec = timeout.tv_sec;
-      tv.tv_usec = timeout.tv_usec;
-      
-      int result = select(FD_SETSIZE, &rd, &wr, &ex, &tv);
-      assert(result != -1 || errno == EINTR);
-    }
+        UnGuard unguard(mutex_);
+        
+        if (timeout < TimeVal(0))
+          timeout = TimeVal(0);
+        
+        struct timeval tv;
+        tv.tv_sec = timeout.tv_sec;
+        tv.tv_usec = timeout.tv_usec;
+        
+        result = select(FD_SETSIZE, &rd, &wr, &ex, &tv);
+        assert(result != -1 || errno == EINTR);
+      }
+    } while(result == -1 && errno == EINTR);
 
-    // check after select, we might have caught a signal
+    // check if we've been asked to exit.  If so, exit early.
     if (do_exit_)
       break;
 




Reply via email to