Use poll() instead of select() for the server main loop.
Fixed races with SIGCHLD handling and ptrace.
Minor fixes to timeout handling.

diff --git a/server/pipe.c b/server/pipe.c
index 5459f3e..f449ca6 100644
--- a/server/pipe.c
+++ b/server/pipe.c
@@ -33,7 +33,8 @@
 {
     struct object       obj;         /* object header */
     struct pipe        *other;       /* the pipe other end */
-    struct select_user  select;      /* select user */
+    int                 fd;          /* file descriptor */
+    int                 select;      /* select user id */
     enum side           side;        /* which side of the pipe is this */
 };
 
@@ -68,12 +69,14 @@
 
     if ((pipe = alloc_object( &pipe_ops )))
     {
-        pipe->select.fd      = fd;
-        pipe->select.func    = default_select_event;
-        pipe->select.private = pipe;
-        pipe->other          = NULL;
-        pipe->side           = side;
-        register_select_user( &pipe->select );
+        pipe->fd     = fd;
+        pipe->other  = NULL;
+        pipe->side   = side;
+        if ((pipe->select = add_select_user( fd, default_select_event, pipe )) == -1)
+        {
+            release_object( pipe );
+            pipe = NULL;
+        }
     }
     return pipe;
 }
@@ -111,7 +114,7 @@
     struct pipe *pipe = (struct pipe *)obj;
     assert( obj->ops == &pipe_ops );
     fprintf( stderr, "Pipe %s-side fd=%d\n",
-             (pipe->side == READ_SIDE) ? "read" : "write", pipe->select.fd );
+             (pipe->side == READ_SIDE) ? "read" : "write", pipe->fd );
 }
 
 static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry )
@@ -119,8 +122,7 @@
     struct pipe *pipe = (struct pipe *)obj;
     assert( obj->ops == &pipe_ops );
     if (!obj->head)  /* first on the queue */
-        set_select_events( &pipe->select,
-                           (pipe->side == READ_SIDE) ? READ_EVENT : WRITE_EVENT );
+        set_select_events( pipe->select, (pipe->side == READ_SIDE) ? POLLIN : POLLOUT );
     add_queue( obj, entry );
     return 1;
 }
@@ -132,7 +134,7 @@
 
     remove_queue( obj, entry );
     if (!obj->head)  /* last on the queue is gone */
-        set_select_events( &pipe->select, 0 );
+        set_select_events( pipe->select, 0 );
     release_object( obj );
 }
 
@@ -142,17 +144,17 @@
     struct pipe *pipe = (struct pipe *)obj;
     assert( obj->ops == &pipe_ops );
 
-    event = (pipe->side == READ_SIDE) ? READ_EVENT : WRITE_EVENT;
-    if (check_select_events( &pipe->select, event ))
+    event = (pipe->side == READ_SIDE) ? POLLIN : POLLOUT;
+    if (check_select_events( pipe->fd, event ))
     {
         /* stop waiting on select() if we are signaled */
-        set_select_events( &pipe->select, 0 );
+        set_select_events( pipe->select, 0 );
         return 1;
     }
     else
     {
         /* restart waiting on select() if we are no longer signaled */
-        if (obj->head) set_select_events( &pipe->select, event );
+        if (obj->head) set_select_events( pipe->select, event );
         return 0;
     }
 }
@@ -172,7 +174,7 @@
         set_error( ERROR_ACCESS_DENIED );
         return -1;
     }
-    return dup( pipe->select.fd );
+    return dup( pipe->fd );
 }
 
 static int pipe_get_write_fd( struct object *obj )
@@ -190,7 +192,7 @@
         set_error( ERROR_ACCESS_DENIED );
         return -1;
     }
-    return dup( pipe->select.fd );
+    return dup( pipe->fd );
 }
 
 static int pipe_get_info( struct object *obj, struct get_file_info_request *req )
@@ -214,8 +216,7 @@
     assert( obj->ops == &pipe_ops );
 
     if (pipe->other) pipe->other->other = NULL;
-    unregister_select_user( &pipe->select );
-    close( pipe->select.fd );
+    remove_select_user( pipe->select );
 }
 
 /* create an anonymous pipe */