io_wait: don't update FD watched status on error
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Fri, 18 Jun 2010 07:48:21 +0000 (09:48 +0200)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Fri, 18 Jun 2010 07:48:21 +0000 (09:48 +0200)
If the syscall to change the events or delete a watched FD fails,
don't update/delete the FD status in fd_hash.
For /dev/poll if a change fails when re-adding the FD, delete it
from the hash (in the /dev/poll case to change the events a FD is
watched for one has to remove it and re-add it with the new
events).
The syscalls should never fail in an un-handled way, but in the
unlikely event that it happens this change will make the code more
robust.

io_wait.h

index 93f1426..01df1e6 100644 (file)
--- a/io_wait.h
+++ b/io_wait.h
@@ -627,7 +627,6 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
                goto error;
        }
        events=e->events;
-       unhash_fd_map(e);
        
        switch(h->poll_method){
                case POLL_POLL:
@@ -647,7 +646,6 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
 #endif
 #ifdef HAVE_SIGIO_RT
                case POLL_SIGIO_RT:
-                       fix_fd_array;
                        /* the O_ASYNC flag must be reset all the time, the fd
                         *  can be changed only if  O_ASYNC is reset (if not and
                         *  the fd is a duplicate, you will get signals from the dup. fd
@@ -667,6 +665,7 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
                                                                " failed: %s [%d]\n", strerror(errno), errno); 
                                        goto error; 
                                } 
+                       fix_fd_array; /* only on success */
                        break;
 #endif
 #ifdef HAVE_EPOLL
@@ -737,6 +736,7 @@ again_devpoll:
                                        h->poll_method);
                        goto error;
        }
+       unhash_fd_map(e); /* only on success */
        h->fd_no--;
        return 0;
 error:
@@ -808,14 +808,14 @@ inline static int io_watch_chg(io_wait_h* h, int fd, short events, int idx )
        
        add_events=events & ~e->events;
        del_events=e->events & ~events;
-       e->events=events;
        switch(h->poll_method){
                case POLL_POLL:
+                       fd_array_chg(events
 #ifdef POLLRDHUP
-                       /* listen to POLLRDHUP by default (if POLLIN) */
-                       events|=((int)!(events & POLLIN) - 1) & POLLRDHUP;
+                                                       /* listen to POLLRDHUP by default (if POLLIN) */
+                                                       | (((int)!(events & POLLIN) - 1) & POLLRDHUP)
 #endif /* POLLRDHUP */
-                       fd_array_chg(events);
+                                               );
                        break;
 #ifdef HAVE_SELECT
                case POLL_SELECT:
@@ -921,6 +921,8 @@ again_devpoll2:
                                        LOG(L_ERR, "ERROR: io_watch_chg: re-adding fd to "
                                                                "/dev/poll failed: %s [%d]\n", 
                                                                strerror(errno), errno);
+                                       /* error re-adding the fd => mark it as removed/unhash */
+                                       unhash_fd_map(e);
                                        goto error;
                                }
                                break;
@@ -931,6 +933,7 @@ again_devpoll2:
                                        h->poll_method);
                        goto error;
        }
+       e->events=events; /* only on success */
        return 0;
 error:
        return -1;