Browse code

- io_wait fixes: - use the correct flags fo sigio_rt's sigio_band - call handle_io for POLLERR & POLLHUP even if not specified among the watched events - tcp: - handle POLLERR & POLLHUP (same way as POLLIN)

Andrei Pelinescu-Onciul authored on 11/12/2007 18:19:58
Showing 2 changed files
... ...
@@ -478,7 +478,7 @@ again_devpoll:
478 478
 check_io_again:
479 479
 		while(e->type && ((n=poll(&pf, 1, 0))>0) && 
480 480
 				(handle_io(e, pf.revents, idx)>0) &&
481
-				(pf.revents & e->events));
481
+				(pf.revents & (e->events|POLLERR|POLLHUP)));
482 482
 		if (unlikely(e->type && (n==-1))){
483 483
 			if (errno==EINTR) goto check_io_again;
484 484
 			LOG(L_ERR, "ERROR: io_watch_add: check_io poll: %s [%d]\n",
... ...
@@ -891,8 +891,8 @@ again:
891 891
 				 *  IO and the fd is still watched for the triggering event */
892 892
 				while(fm->type && 
893 893
 						(handle_io(fm, h->fd_array[r].revents, r) > 0) &&
894
-						repeat &&
895
-						(fm->events & h->fd_array[r].revents) );
894
+						repeat && ((fm->events|POLLERR|POLLHUP) &
895
+													h->fd_array[r].revents));
896 896
 			}
897 897
 		}
898 898
 error:
... ...
@@ -974,13 +974,14 @@ again:
974 974
 		}
975 975
 #endif
976 976
 		for (r=0; r<n; r++){
977
-			revents= (POLLIN & (!(h->ep_array[r].events & EPOLLIN)-1)) |
977
+			revents= (POLLIN & (!(h->ep_array[r].events & (EPOLLIN|EPOLLPRI))
978
+						-1)) |
978 979
 					 (POLLOUT & (!(h->ep_array[r].events & EPOLLOUT)-1)) |
979 980
 					 (POLLERR & (!(h->ep_array[r].events & EPOLLERR)-1)) |
980 981
 					 (POLLHUP & (!(h->ep_array[r].events & EPOLLHUP)-1));
981 982
 			if (likely(revents)){
982 983
 				fm=(struct fd_map*)h->ep_array[r].data.ptr;
983
-				while(fm->type && (fm->events & revents) && 
984
+				while(fm->type && ((fm->events|POLLERR|POLLHUP) & revents) && 
984 985
 						(handle_io(fm, revents, -1)>0) && repeat);
985 986
 			}else{
986 987
 				LOG(L_ERR, "ERROR:io_wait_loop_epoll: unexpected event %x"
... ...
@@ -1122,6 +1123,17 @@ again:
1122 1122
 			if (fm->type)
1123 1123
 				handle_io(fm, POLLIN|POLLOUT, -1);
1124 1124
 		}else{
1125
+			/* si_code contains the SIGPOLL reason: POLL_IN, POLL_OUT,
1126
+			 *  POLL_MSG, POLL_ERR, POLL_PRI or POLL_HUP
1127
+			 * and si_band the translated poll event bitmap:
1128
+			 *  POLLIN|POLLRDNORM  (=POLL_IN),
1129
+			 *  POLLOUT|POLLWRNORM|POLLWRBAND (=POLL_OUT),
1130
+			 *  POLLIN|POLLRDNORM|POLLMSG (=POLL_MSG),
1131
+			 *  POLLERR (=POLL_ERR),
1132
+			 *  POLLPRI|POLLRDBAND (=POLL_PRI),
1133
+			 *  POLLHUP|POLLERR (=POLL_HUP) 
1134
+			 *  [linux 2.6.22 fs/fcntl.c:447]
1135
+			 */
1125 1136
 #ifdef EXTRA_DEBUG
1126 1137
 			DBG("io_wait_loop_sigio_rt: siginfo: signal=%d (%d),"
1127 1138
 					" si_code=%d, si_band=0x%x,"
... ...
@@ -1131,23 +1143,24 @@ again:
1131 1131
 					sigio_fd);
1132 1132
 #endif
1133 1133
 			/* on some errors (e.g. when receving TCP RST), sigio_band will
1134
-			 * be set to 0x08 (undocumented, no corresp. POLL_xx), so better
1135
-			 * catch all events --andrei */
1136
-			if (likely(sigio_band)/*&(POLL_IN|POLL_ERR|POLL_HUP)*/){
1134
+			 * be set to 0x08 (POLLERR) or 0x18 (POLLERR|POLLHUP - on stream
1135
+			 *  unix socket close) , so better catch all events --andrei */
1136
+			if (likely(sigio_band)){
1137 1137
 				fm=get_fd_map(h, sigio_fd);
1138
-				revents=(POLLIN & (!(sigio_band & POLL_IN)-1)) |
1139
-						(POLLOUT & (!(sigio_band & POLL_OUT)-1)) |
1140
-						(POLLERR & (!(sigio_band & POLL_ERR)-1)) |
1141
-						(POLLHUP & (!(sigio_band & POLL_HUP)-1));
1138
+				revents=sigio_band;
1139
+				/* fix revents==POLLPRI case */
1140
+				revents |= (!(revents & POLLPRI)-1) & POLLIN;
1142 1141
 				/* we can have queued signals generated by fds not watched
1143 1142
 			 	 * any more, or by fds in transition, to a child 
1144 1143
 				 * => ignore them */
1145
-				if (fm->type && (fm->events & revents))
1144
+				if (fm->type && ((fm->events|POLLERR|POLLHUP) & revents))
1146 1145
 					handle_io(fm, revents, -1);
1147 1146
 				else
1148
-					LOG(L_ERR, "WARNING: io_wait_loop_sigio_rt: ignoring event"
1149
-							" %x on fd %d (fm->fd=%d, fm->data=%p)\n",
1150
-							sigio_band, sigio_fd, fm->fd, fm->data);
1147
+					DBG("WARNING: io_wait_loop_sigio_rt: ignoring event"
1148
+							" %x on fd %d, watching for %x, si_code=%x "
1149
+							"(fm->type=%d, fm->fd=%d, fm->data=%p)\n",
1150
+							sigio_band, sigio_fd, fm->events, siginfo.si_code,
1151
+							fm->type, fm->fd, fm->data);
1151 1152
 			}else{
1152 1153
 				LOG(L_ERR, "ERROR: io_wait_loop_sigio_rt: unexpected event"
1153 1154
 							" on fd %d: %x\n", sigio_fd, sigio_band);
... ...
@@ -2523,8 +2523,13 @@ inline static int handle_tcpconn_ev(struct tcp_connection* tcpconn, short ev,
2523 2523
 					goto error;
2524 2524
 			}
2525 2525
 		}
2526
+		ev&=~POLLOUT; /* clear POLLOUT */
2526 2527
 	}
2527
-	if (likely((ev & POLLIN) && !(tcpconn->flags & F_CONN_REMOVED))){
2528
+	if (likely(ev && !(tcpconn->flags & F_CONN_REMOVED))){
2529
+		/* if still some other IO event (POLLIN|POLLHUP|POLLERR) and
2530
+		 * connection is still watched in tcp_main for reads, send it to a
2531
+		 * child and stop watching it for input (but continue watching for
2532
+		 *  writes if needed): */
2528 2533
 		if (unlikely(tcpconn->flags & F_CONN_WRITE_W)){
2529 2534
 			if (unlikely(io_watch_chg(&io_h, tcpconn->s, POLLOUT, fd_i)==-1))
2530 2535
 				goto error;