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/sock.c b/server/sock.c
index 22c5c81..cb9928f 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -42,7 +42,8 @@
 struct sock
 {
     struct object       obj;         /* object header */
-    struct select_user  select;      /* select user */
+    int                 fd;          /* file descriptor */
+    int                 select;      /* select user */
     unsigned int        state;       /* status bits */
     unsigned int        mask;        /* event mask */
     unsigned int        hmask;       /* held (blocked) events */
@@ -77,17 +78,17 @@
 static int sock_event( struct sock *sock )
 {
     unsigned int mask = sock->mask & sock->state & ~sock->hmask;
-    int ev = EXCEPT_EVENT;
+    int ev = 0;
 
     if (sock->state & WS_FD_CONNECT)
         /* connecting, wait for writable */
-        return WRITE_EVENT | EXCEPT_EVENT;
+        return POLLOUT;
     if (sock->state & WS_FD_LISTENING)
         /* listening, wait for readable */
-        return ((sock->hmask & FD_ACCEPT) ? 0 : READ_EVENT) | EXCEPT_EVENT;
+        return (sock->hmask & FD_ACCEPT) ? 0 : POLLIN;
 
-    if (mask & FD_READ)  ev |= READ_EVENT;
-    if (mask & FD_WRITE) ev |= WRITE_EVENT;
+    if (mask & FD_READ)  ev |= POLLIN;
+    if (mask & FD_WRITE) ev |= POLLOUT;
     return ev;
 }
 
@@ -95,8 +96,8 @@
 {
     int ev = sock_event( sock );
     if (debug_level)
-        fprintf(stderr,"sock_reselect(%d): new mask %x\n", sock->select.fd, ev);
-    set_select_events( &sock->select, ev );
+        fprintf(stderr,"sock_reselect(%d): new mask %x\n", sock->fd, ev);
+    set_select_events( sock->select, ev );
 }
 
 inline static int sock_error(int s)
@@ -114,11 +115,11 @@
     unsigned int emask;
     assert( sock->obj.ops == &sock_ops );
     if (debug_level)
-        fprintf(stderr, "socket %d select event: %x\n", sock->select.fd, event);
+        fprintf(stderr, "socket %d select event: %x\n", sock->fd, event);
     if (sock->state & WS_FD_CONNECT)
     {
         /* connecting */
-        if (event & WRITE_EVENT)
+        if (event & POLLOUT)
         {
             /* we got connected */
             sock->state |= WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE;
@@ -126,43 +127,43 @@
             sock->pmask |= FD_CONNECT;
             sock->errors[FD_CONNECT_BIT] = 0;
             if (debug_level)
-                fprintf(stderr, "socket %d connection success\n", sock->select.fd);
+                fprintf(stderr, "socket %d connection success\n", sock->fd);
         }
-        else if (event & EXCEPT_EVENT)
+        else if (event & (POLLERR|POLLHUP))
         {
             /* we didn't get connected? */
             sock->state &= ~WS_FD_CONNECT;
             sock->pmask |= FD_CONNECT;
-            sock->errors[FD_CONNECT_BIT] = sock_error( sock->select.fd );
+            sock->errors[FD_CONNECT_BIT] = sock_error( sock->fd );
             if (debug_level)
-                fprintf(stderr, "socket %d connection failure\n", sock->select.fd);
+                fprintf(stderr, "socket %d connection failure\n", sock->fd);
         }
     } else
     if (sock->state & WS_FD_LISTENING)
     {
         /* listening */
-        if (event & READ_EVENT)
+        if (event & POLLIN)
         {
             /* incoming connection */
             sock->pmask |= FD_ACCEPT;
             sock->errors[FD_ACCEPT_BIT] = 0;
             sock->hmask |= FD_ACCEPT;
         }
-        else if (event & EXCEPT_EVENT)
+        else if (event & (POLLERR|POLLHUP))
         {
             /* failed incoming connection? */
             sock->pmask |= FD_ACCEPT;
-            sock->errors[FD_ACCEPT_BIT] = sock_error( sock->select.fd );
+            sock->errors[FD_ACCEPT_BIT] = sock_error( sock->fd );
             sock->hmask |= FD_ACCEPT;
         }
     } else
     {
         /* normal data flow */
-        if (event & READ_EVENT)
+        if (event & POLLIN)
         {
             /* make sure there's data here */
             int bytes = 0;
-            ioctl(sock->select.fd, FIONREAD, (char*)&bytes);
+            ioctl(sock->fd, FIONREAD, (char*)&bytes);
             if (bytes)
             {
                 /* incoming data */
@@ -170,7 +171,7 @@
                 sock->hmask |= FD_READ;
                 sock->errors[FD_READ_BIT] = 0;
                 if (debug_level)
-                    fprintf(stderr, "socket %d has %d bytes\n", sock->select.fd, bytes);
+                    fprintf(stderr, "socket %d has %d bytes\n", sock->fd, bytes);
             }
             else
             {
@@ -179,27 +180,27 @@
                 sock->pmask |= FD_CLOSE;
                 sock->errors[FD_CLOSE_BIT] = 0;
                 if (debug_level)
-                    fprintf(stderr, "socket %d is closing\n", sock->select.fd);
+                    fprintf(stderr, "socket %d is closing\n", sock->fd);
             }
         }
-        if (event & WRITE_EVENT)
+        if (event & POLLOUT)
         {
             sock->pmask |= FD_WRITE;
             sock->hmask |= FD_WRITE;
             sock->errors[FD_WRITE_BIT] = 0;
             if (debug_level)
-                fprintf(stderr, "socket %d is writable\n", sock->select.fd);
+                fprintf(stderr, "socket %d is writable\n", sock->fd);
         }
-        if (event & EXCEPT_EVENT)
+        if (event & (POLLERR|POLLHUP))
         {
-            sock->errors[FD_CLOSE_BIT] = sock_error( sock->select.fd );
+            sock->errors[FD_CLOSE_BIT] = sock_error( sock->fd );
             if (sock->errors[FD_CLOSE_BIT])
             {
                 /* we got an error, socket closing? */
                 sock->state &= ~(WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE);
                 sock->pmask |= FD_CLOSE;
                 if (debug_level)
-                    fprintf(stderr, "socket %d aborted by error %d\n", sock->select.fd, sock->errors[FD_CLOSE_BIT]);
+                    fprintf(stderr, "socket %d aborted by error %d\n", sock->fd, sock->errors[FD_CLOSE_BIT]);
             }
             else
             {
@@ -207,7 +208,7 @@
                 sock->pmask |= FD_OOB;
                 sock->hmask |= FD_OOB;
                 if (debug_level)
-                    fprintf(stderr, "socket %d got OOB data\n", sock->select.fd);
+                    fprintf(stderr, "socket %d got OOB data\n", sock->fd);
             }
         }
     }
@@ -216,7 +217,7 @@
     /* wake up anyone waiting for whatever just happened */
     emask = sock->pmask & sock->mask;
     if (debug_level && emask)
-        fprintf(stderr, "socket %d pending events: %x\n", sock->select.fd, emask);
+        fprintf(stderr, "socket %d pending events: %x\n", sock->fd, emask);
     if (emask && sock->event) {
         if (debug_level) fprintf(stderr, "signalling event ptr %p\n", sock->event);
         set_event(sock->event);
@@ -232,7 +233,7 @@
     struct sock *sock = (struct sock *)obj;
     assert( obj->ops == &sock_ops );
     printf( "Socket fd=%d, state=%x, mask=%x, pending=%x, held=%x\n",
-            sock->select.fd, sock->state,
+            sock->fd, sock->state,
             sock->mask, sock->pmask, sock->hmask );
 }
 
@@ -259,7 +260,7 @@
     struct sock *sock = (struct sock *)obj;
     assert( obj->ops == &sock_ops );
 
-    return check_select_events( &sock->select, sock_event( sock ) );
+    return check_select_events( sock->fd, sock_event( sock ) );
 }
 
 static int sock_get_fd( struct object *obj )
@@ -267,7 +268,7 @@
     struct sock *sock = (struct sock *)obj;
     int fd;
     assert( obj->ops == &sock_ops );
-    fd = dup( sock->select.fd );
+    fd = dup( sock->fd );
     if (fd==-1)
     	sock_set_error();
     return fd;
@@ -278,9 +279,8 @@
     struct sock *sock = (struct sock *)obj;
     assert( obj->ops == &sock_ops );
 
-    unregister_select_user( &sock->select );
     /* FIXME: special socket shutdown stuff? */
-    close( sock->select.fd );
+    remove_select_user( sock->select );
     if (sock->event)
     {
         /* if the service thread was waiting for the event object,
@@ -311,15 +311,17 @@
         close( sockfd );
         return NULL;
     }
-    sock->select.fd      = sockfd;
-    sock->select.func    = sock_select_event;
-    sock->select.private = sock;
-    sock->state          = (type!=SOCK_STREAM) ? WS_FD_READ|WS_FD_WRITE : 0;
-    sock->mask           = 0;
-    sock->hmask          = 0;
-    sock->pmask          = 0;
-    sock->event          = NULL;
-    register_select_user( &sock->select );
+    sock->fd    = sockfd;
+    sock->state = (type!=SOCK_STREAM) ? WS_FD_READ|WS_FD_WRITE : 0;
+    sock->mask  = 0;
+    sock->hmask = 0;
+    sock->pmask = 0;
+    sock->event = NULL;
+    if ((sock->select = add_select_user( sockfd, sock_select_event, sock )) == -1)
+    {
+        release_object( sock );
+        return NULL;
+    }
     sock_reselect( sock );
     clear_error();
     return &sock->obj;
@@ -343,7 +345,7 @@
      * return.
      */
     slen = sizeof(saddr);
-    acceptfd = accept(sock->select.fd,&saddr,&slen);
+    acceptfd = accept(sock->fd,&saddr,&slen);
     if (acceptfd==-1) {
     	sock_set_error();
         release_object( sock );
@@ -356,19 +358,21 @@
         return NULL;
     }
 
-    acceptsock->select.fd      = acceptfd;
-    acceptsock->select.func    = sock_select_event;
-    acceptsock->select.private = acceptsock;
-    acceptsock->state          = WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE;
-    acceptsock->mask           = sock->mask;
-    acceptsock->hmask          = 0;
-    acceptsock->pmask          = 0;
-    if (sock->event)
-        acceptsock->event          = (struct event *)grab_object( sock->event );
-    else
-        acceptsock->event          = NULL;
+    acceptsock->fd     = acceptfd;
+    acceptsock->state  = WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE;
+    acceptsock->mask   = sock->mask;
+    acceptsock->hmask  = 0;
+    acceptsock->pmask  = 0;
+    acceptsock->event  = NULL;
+    acceptsock->select = add_select_user( acceptfd, sock_select_event, acceptsock );
+    if (acceptsock->select == -1)
+    {
+        release_object( acceptsock );
+        release_object( sock );
+        return NULL;
+    }
+    if (sock->event) acceptsock->event = (struct event *)grab_object( sock->event );
 
-    register_select_user( &acceptsock->select );
     sock_reselect( acceptsock );
     clear_error();
     sock->pmask &= ~FD_ACCEPT;