Browse code

io_wait: don't update FD watched status on error

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.

Andrei Pelinescu-Onciul authored on 18/06/2010 07:48:21
Showing 1 changed files
... ...
@@ -627,7 +627,6 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
627 627
 		goto error;
628 628
 	}
629 629
 	events=e->events;
630
-	unhash_fd_map(e);
631 630
 	
632 631
 	switch(h->poll_method){
633 632
 		case POLL_POLL:
... ...
@@ -647,7 +646,6 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
647 647
 #endif
648 648
 #ifdef HAVE_SIGIO_RT
649 649
 		case POLL_SIGIO_RT:
650
-			fix_fd_array;
651 650
 			/* the O_ASYNC flag must be reset all the time, the fd
652 651
 			 *  can be changed only if  O_ASYNC is reset (if not and
653 652
 			 *  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)
667 667
 								" failed: %s [%d]\n", strerror(errno), errno); 
668 668
 					goto error; 
669 669
 				} 
670
+			fix_fd_array; /* only on success */
670 671
 			break;
671 672
 #endif
672 673
 #ifdef HAVE_EPOLL
... ...
@@ -737,6 +736,7 @@ again_devpoll:
737 737
 					h->poll_method);
738 738
 			goto error;
739 739
 	}
740
+	unhash_fd_map(e); /* only on success */
740 741
 	h->fd_no--;
741 742
 	return 0;
742 743
 error:
... ...
@@ -808,14 +808,14 @@ inline static int io_watch_chg(io_wait_h* h, int fd, short events, int idx )
808 808
 	
809 809
 	add_events=events & ~e->events;
810 810
 	del_events=e->events & ~events;
811
-	e->events=events;
812 811
 	switch(h->poll_method){
813 812
 		case POLL_POLL:
813
+			fd_array_chg(events
814 814
 #ifdef POLLRDHUP
815
-			/* listen to POLLRDHUP by default (if POLLIN) */
816
-			events|=((int)!(events & POLLIN) - 1) & POLLRDHUP;
815
+							/* listen to POLLRDHUP by default (if POLLIN) */
816
+							| (((int)!(events & POLLIN) - 1) & POLLRDHUP)
817 817
 #endif /* POLLRDHUP */
818
-			fd_array_chg(events);
818
+						);
819 819
 			break;
820 820
 #ifdef HAVE_SELECT
821 821
 		case POLL_SELECT:
... ...
@@ -921,6 +921,8 @@ again_devpoll2:
921 921
 					LOG(L_ERR, "ERROR: io_watch_chg: re-adding fd to "
922 922
 								"/dev/poll failed: %s [%d]\n", 
923 923
 								strerror(errno), errno);
924
+					/* error re-adding the fd => mark it as removed/unhash */
925
+					unhash_fd_map(e);
924 926
 					goto error;
925 927
 				}
926 928
 				break;
... ...
@@ -931,6 +933,7 @@ again_devpoll2:
931 931
 					h->poll_method);
932 932
 			goto error;
933 933
 	}
934
+	e->events=events; /* only on success */
934 935
 	return 0;
935 936
 error:
936 937
 	return -1;