Skip to content
This repository
Browse code

Merge branch 'new-events' into dev

  • Loading branch information...
commit 9a8b3492f666798f82b41e217e0db38eb21bad5f 2 parents 3976ff1 + 2a60fad
Alvaro Lopez Ortega authored January 05, 2012
2  cherokee/Makefile.am
@@ -1577,6 +1577,8 @@ $(common_rrd_tools) \
1577 1577
 \
1578 1578
 connection.h \
1579 1579
 connection-protected.h \
  1580
+connection-poll.h \
  1581
+connection-poll.c \
1580 1582
 connection.c \
1581 1583
 handler.h \
1582 1584
 handler.c \
25  cherokee/bind.c
@@ -171,33 +171,12 @@ set_socket_opts (int socket)
171 171
 	if (ret != ret_ok)
172 172
 		return ret;
173 173
 
174  
-	/* TCP_MAXSEG:
175  
-	 * The maximum size of a TCP segment is based on the network MTU for des-
176  
-	 * tinations on local networks or on a default MTU of 576 bytes for desti-
177  
-	 * nations on nonlocal networks.  The default behavior can be altered by
178  
-	 * setting the TCP_MAXSEG option to an integer value from 1 to 65,535.
179  
-	 * However, TCP will not use a maximum segment size smaller than 32 or
180  
-	 * larger than the local network MTU.  Setting the TCP_MAXSEG option to a
181  
-	 * value of zero results in default behavior.  The TCP_MAXSEG option can
182  
-	 * only be set prior to calling listen or connect on the socket.  For pas-
183  
-	 * sive connections, the TCP_MAXSEG option value is inherited from the
184  
-	 * listening socket. This option takes an int value, with a range of 0 to
185  
-	 * 65535.
186  
-	 */
187  
-#ifdef TCP_MAXSEG
188  
-	on = 64000;
189  
-	setsockopt (socket, SOL_SOCKET, TCP_MAXSEG, &on, sizeof(on));
190  
-
191  
-	/* Do no check the returned value */
192  
-#endif
193  
-
194 174
 	/* TCP_DEFER_ACCEPT:
195 175
 	 * Allows a listener to be awakened only when data arrives on the socket.
196 176
 	 * Takes an integer value (seconds), this can bound the maximum number of
197  
-	 * attempts TCP will make to complete the connection. This option should
198  
-	 * not be used in code intended to be portable.
  177
+	 * attempts TCP will make to complete the connection.
199 178
 	 *
200  
-	 * Give clients 5s to send first data packet
  179
+	 * Gives clients 5secs to send the first data packet
201 180
 	 */
202 181
 #ifdef TCP_DEFER_ACCEPT
203 182
 	on = 5;
58  cherokee/connection-poll.c
... ...
@@ -0,0 +1,58 @@
  1
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
  2
+
  3
+/* Cherokee
  4
+ *
  5
+ * Authors:
  6
+ *      Alvaro Lopez Ortega <alvaro@alobbs.com>
  7
+ *
  8
+ * Copyright (C) 2001-2011 Alvaro Lopez Ortega
  9
+ *
  10
+ * This program is free software; you can redistribute it and/or
  11
+ * modify it under the terms of version 2 of the GNU General Public
  12
+ * License as published by the Free Software Foundation.
  13
+ *
  14
+ * This program is distributed in the hope that it will be useful,
  15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17
+ * GNU General Public License for more details.
  18
+ *
  19
+ * You should have received a copy of the GNU General Public License
  20
+ * along with this program; if not, write to the Free Software
  21
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  22
+ * 02110-1301, USA.
  23
+ */
  24
+
  25
+#include "common-internal.h"
  26
+#include "connection-poll.h"
  27
+
  28
+ret_t
  29
+cherokee_connection_poll_init (cherokee_connection_pool_t *conn_poll)
  30
+{
  31
+	conn_poll->fd   = -1;
  32
+	conn_poll->mode = poll_mode_nothing;
  33
+
  34
+	return ret_ok;
  35
+}
  36
+
  37
+ret_t
  38
+cherokee_connection_poll_mrproper (cherokee_connection_pool_t *conn_poll)
  39
+{
  40
+	UNUSED (conn_poll);
  41
+	return ret_ok;
  42
+}
  43
+
  44
+ret_t
  45
+cherokee_connection_poll_clean (cherokee_connection_pool_t *conn_poll)
  46
+{
  47
+	conn_poll->fd   = -1;
  48
+	conn_poll->mode = poll_mode_nothing;
  49
+
  50
+	return ret_ok;
  51
+}
  52
+
  53
+int
  54
+cherokee_connection_poll_is_set (cherokee_connection_pool_t *conn_poll)
  55
+{
  56
+	return ((conn_poll->fd != -1) ||
  57
+		(conn_poll->mode != poll_mode_nothing));
  58
+}
47  cherokee/connection-poll.h
... ...
@@ -0,0 +1,47 @@
  1
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
  2
+
  3
+/* Cherokee
  4
+ *
  5
+ * Authors:
  6
+ *      Alvaro Lopez Ortega <alvaro@alobbs.com>
  7
+ *
  8
+ * Copyright (C) 2001-2011 Alvaro Lopez Ortega
  9
+ *
  10
+ * This program is free software; you can redistribute it and/or
  11
+ * modify it under the terms of version 2 of the GNU General Public
  12
+ * License as published by the Free Software Foundation.
  13
+ *
  14
+ * This program is distributed in the hope that it will be useful,
  15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17
+ * GNU General Public License for more details.
  18
+ *
  19
+ * You should have received a copy of the GNU General Public License
  20
+ * along with this program; if not, write to the Free Software
  21
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  22
+ * 02110-1301, USA.
  23
+ */
  24
+
  25
+#if !defined (CHEROKEE_INSIDE_CHEROKEE_H) && !defined (CHEROKEE_COMPILATION)
  26
+# error "Only <cherokee/cherokee.h> can be included directly, this file may disappear or change contents."
  27
+#endif
  28
+
  29
+#ifndef CHEROKEE_CONNECTION_POLL_H
  30
+#define CHEROKEE_CONNECTION_POLL_H
  31
+
  32
+#include "common.h"
  33
+#include "fdpoll.h"
  34
+
  35
+
  36
+typedef struct {
  37
+	cherokee_poll_mode_t mode;
  38
+	int                  fd;
  39
+} cherokee_connection_pool_t;
  40
+
  41
+
  42
+ret_t cherokee_connection_poll_init     (cherokee_connection_pool_t *conn_poll);
  43
+ret_t cherokee_connection_poll_clean    (cherokee_connection_pool_t *conn_poll);
  44
+ret_t cherokee_connection_poll_mrproper (cherokee_connection_pool_t *conn_poll);
  45
+int   cherokee_connection_poll_is_set   (cherokee_connection_pool_t *conn_poll);
  46
+
  47
+#endif /* CHEROKEE_CONNECTION_POLL_H */
14  cherokee/connection-protected.h
@@ -68,6 +68,7 @@
68 68
 #include "bind.h"
69 69
 #include "bogotime.h"
70 70
 #include "config_entry.h"
  71
+#include "connection-poll.h"
71 72
 
72 73
 typedef enum {
73 74
 	phase_nothing,
@@ -89,10 +90,9 @@ typedef enum {
89 90
 #define conn_op_root_index        (1 << 1)
90 91
 #define conn_op_tcp_cork          (1 << 2)
91 92
 #define conn_op_document_root     (1 << 3)
92  
-#define conn_op_was_polling       (1 << 4)
93  
-#define conn_op_cant_encoder      (1 << 5)
94  
-#define conn_op_got_eof           (1 << 6)
95  
-#define conn_op_chunked_formatted (1 << 7)
  93
+#define conn_op_cant_encoder      (1 << 4)
  94
+#define conn_op_got_eof           (1 << 5)
  95
+#define conn_op_chunked_formatted (1 << 6)
96 96
 
97 97
 typedef cuint_t cherokee_connection_options_t;
98 98
 
@@ -192,9 +192,7 @@ struct cherokee_connection {
192 192
 
193 193
 	/* Polling
194 194
 	 */
195  
-	int                           polling_fd;
196  
-	cherokee_socket_status_t      polling_mode;
197  
-	cherokee_boolean_t            polling_multiple;
  195
+	cherokee_connection_pool_t    polling_aim;
198 196
 
199 197
 	off_t                         range_start;
200 198
 	off_t                         range_end;
@@ -254,7 +252,7 @@ struct cherokee_connection {
254 252
  */
255 253
 ret_t cherokee_connection_new                    (cherokee_connection_t **conn);
256 254
 ret_t cherokee_connection_free                   (cherokee_connection_t  *conn);
257  
-ret_t cherokee_connection_clean                  (cherokee_connection_t  *conn);
  255
+ret_t cherokee_connection_clean                  (cherokee_connection_t  *conn, cherokee_boolean_t reuse);
258 256
 ret_t cherokee_connection_clean_close            (cherokee_connection_t  *conn);
259 257
 
260 258
 /* Close
133  cherokee/connection.c
@@ -120,9 +120,6 @@ cherokee_connection_new  (cherokee_connection_t **conn)
120 120
 	n->timeout                   = -1;
121 121
 	n->timeout_lapse             = -1;
122 122
 	n->timeout_header            = NULL;
123  
-	n->polling_fd                = -1;
124  
-	n->polling_multiple          = false;
125  
-	n->polling_mode              = FDPOLL_MODE_NONE;
126 123
 	n->expiration                = cherokee_expiration_none;
127 124
 	n->expiration_time           = 0;
128 125
 	n->expiration_prop           = cherokee_expiration_prop_none;
@@ -158,7 +155,8 @@ cherokee_connection_new  (cherokee_connection_t **conn)
158 155
 
159 156
 	cherokee_socket_init (&n->socket);
160 157
 	cherokee_header_init (&n->header, header_type_request);
161  
-	cherokee_post_init (&n->post);
  158
+	cherokee_post_init (&n->post, n);
  159
+	cherokee_connection_poll_init (&n->polling_aim);
162 160
 
163 161
 	memset (n->regex_ovector, 0, OVECTOR_LEN * sizeof(int));
164 162
 	n->regex_ovecsize = 0;
@@ -232,11 +230,11 @@ cherokee_connection_free (cherokee_connection_t  *conn)
232 230
 		conn->arguments = NULL;
233 231
 	}
234 232
 
235  
-        if (conn->polling_fd != -1) {
236  
-                cherokee_fd_close (conn->polling_fd);
237  
-                conn->polling_fd   = -1;
238  
-		conn->polling_mode = FDPOLL_MODE_NONE;
239  
-        }
  233
+
  234
+	if (conn->polling_aim.fd != -1) {
  235
+                cherokee_fd_close (conn->polling_aim.fd);
  236
+	}
  237
+	cherokee_connection_poll_mrproper (&conn->polling_aim);
240 238
 
241 239
 	free (conn);
242 240
 	return ret_ok;
@@ -244,7 +242,8 @@ cherokee_connection_free (cherokee_connection_t  *conn)
244 242
 
245 243
 
246 244
 ret_t
247  
-cherokee_connection_clean (cherokee_connection_t *conn)
  245
+cherokee_connection_clean (cherokee_connection_t *conn,
  246
+			   cherokee_boolean_t     reuse)
248 247
 {
249 248
 	size_t             crlf_len;
250 249
 	uint32_t           header_len;
@@ -289,10 +288,10 @@ cherokee_connection_clean (cherokee_connection_t *conn)
289 288
 	conn->encoder_new_func = NULL;
290 289
 	conn->encoder_props    = NULL;
291 290
 
292  
-	if (conn->polling_fd != -1) {
293  
-		cherokee_fd_close (conn->polling_fd);
294  
-		conn->polling_fd = -1;
  291
+	if (conn->polling_aim.fd != -1) {
  292
+                cherokee_fd_close (conn->polling_aim.fd);
295 293
 	}
  294
+	cherokee_connection_poll_clean (&conn->polling_aim);
296 295
 
297 296
 	if (conn->validator != NULL) {
298 297
 		cherokee_validator_free (conn->validator);
@@ -315,8 +314,6 @@ cherokee_connection_clean (cherokee_connection_t *conn)
315 314
 	conn->rx_partial           = 0;
316 315
 	conn->tx_partial           = 0;
317 316
 	conn->traffic_next         = 0;
318  
-	conn->polling_multiple     = false;
319  
-	conn->polling_mode         = FDPOLL_MODE_NONE;
320 317
 	conn->expiration           = cherokee_expiration_none;
321 318
 	conn->expiration_time      = 0;
322 319
 	conn->expiration_prop      = cherokee_expiration_prop_none;
@@ -333,6 +330,8 @@ cherokee_connection_clean (cherokee_connection_t *conn)
333 330
 	memset (conn->regex_host_ovector, 0, OVECTOR_LEN * sizeof(int));
334 331
 	conn->regex_host_ovecsize = 0;
335 332
 
  333
+	cherokee_connection_poll_clean (&conn->polling_aim);
  334
+
336 335
 	cherokee_post_clean (&conn->post);
337 336
 	cherokee_buffer_mrproper (&conn->encoder_buffer);
338 337
 
@@ -373,27 +372,24 @@ cherokee_connection_clean (cherokee_connection_t *conn)
373 372
 	cherokee_buffer_clean (&conn->buffer);
374 373
 	cherokee_buffer_clean (&conn->header_buffer);
375 374
 
376  
-	/* Skip trailing CRLF (which may be sent by some HTTP clients)
377  
-	 * only if the number of CRLFs is within the predefine count
378  
-	 * limit otherwise ignore trailing CRLFs so that they will be
379  
-	 * handled in next request.  This may avoid a subsequent real
380  
-	 * move_to_begin of the contents left in the buffer.
381  
-	 */
382  
-	crlf_len = cherokee_buffer_cnt_spn (&conn->incoming_header, header_len, CRLF);
383  
-	header_len += (crlf_len <= MAX_HEADER_CRLF) ? crlf_len : 0;
  375
+	if (reuse) {
  376
+		/* Skip trailing CRLF (which may be sent by some HTTP clients)
  377
+		 * only if the number of CRLFs is within the predefine count
  378
+		 * limit otherwise ignore trailing CRLFs so that they will be
  379
+		 * handled in next request.  This may avoid a subsequent real
  380
+		 * move_to_begin of the contents left in the buffer.
  381
+		 */
  382
+		crlf_len = cherokee_buffer_cnt_spn (&conn->incoming_header, header_len, CRLF);
  383
+		header_len += (crlf_len <= MAX_HEADER_CRLF) ? crlf_len : 0;
384 384
 
385  
-	cherokee_buffer_move_to_begin (&conn->incoming_header, header_len);
  385
+		cherokee_buffer_move_to_begin (&conn->incoming_header, header_len);
386 386
 
387  
-	/* If the connection has incoming headers to be processed,
388  
-	 * then increment the pending counter from the thread
389  
-	 */
390  
-	if (! cherokee_buffer_is_empty (&conn->incoming_header)) {
391  
-		CONN_THREAD(conn)->pending_conns_num++;
  387
+		TRACE (ENTRIES, "conn %p, %s headers\n", conn,
  388
+		       !cherokee_buffer_is_empty (&conn->incoming_header) ? "has" : "doesn't have");
  389
+	} else {
  390
+		cherokee_buffer_clean (&conn->incoming_header);
392 391
 	}
393 392
 
394  
-	TRACE (ENTRIES, "conn %p, has headers %d\n", conn,
395  
-	       !cherokee_buffer_is_empty (&conn->incoming_header));
396  
-
397 393
 	return ret_ok;
398 394
 }
399 395
 
@@ -413,7 +409,7 @@ cherokee_connection_clean_close (cherokee_connection_t *conn)
413 409
 
414 410
 	/* Clean the connection object
415 411
 	 */
416  
-	cherokee_connection_clean (conn);
  412
+	cherokee_connection_clean (conn, false);
417 413
 	return ret_ok;
418 414
 }
419 415
 
@@ -1057,8 +1053,12 @@ cherokee_connection_send_header_and_mmaped (cherokee_connection_t *conn)
1057 1053
 		if (unlikely (ret != ret_ok) ) {
1058 1054
 			switch (ret) {
1059 1055
 			case ret_eof:
  1056
+				return ret_eof;
  1057
+
1060 1058
 			case ret_eagain:
1061  
-				return ret;
  1059
+				conn->polling_aim.fd   = conn->socket.socket;
  1060
+				conn->polling_aim.mode = poll_mode_write;
  1061
+				return ret_eagain;
1062 1062
 
1063 1063
 			case ret_error:
1064 1064
 				conn->keepalive = 0;
@@ -1095,8 +1095,12 @@ cherokee_connection_send_header_and_mmaped (cherokee_connection_t *conn)
1095 1095
 		switch (ret) {
1096 1096
 
1097 1097
 		case ret_eof:
  1098
+			return ret_eof;
  1099
+
1098 1100
 		case ret_eagain:
1099  
-			return ret;
  1101
+			conn->polling_aim.fd   = conn->socket.socket;
  1102
+			conn->polling_aim.mode = poll_mode_write;
  1103
+			return ret_eagain;
1100 1104
 
1101 1105
 		case ret_error:
1102 1106
 			conn->keepalive = 0;
@@ -1188,15 +1192,15 @@ cherokee_connection_recv (cherokee_connection_t *conn,
1188 1192
 		return ret;
1189 1193
 
1190 1194
 	case ret_eagain:
1191  
-		if (cherokee_socket_pending_read (&conn->socket)) {
1192  
-			CONN_THREAD(conn)->pending_read_num += 1;
1193  
-		}
1194  
-
1195 1195
 		if (cnt_read > 0) {
1196 1196
 			cherokee_connection_rx_add (conn, cnt_read);
1197 1197
 			*len = cnt_read;
1198 1198
 			return ret_ok;
1199 1199
 		}
  1200
+
  1201
+		conn->polling_aim.fd   = conn->socket.socket;
  1202
+		conn->polling_aim.mode = poll_mode_read;
  1203
+
1200 1204
 		return ret_eagain;
1201 1205
 
1202 1206
 	default:
@@ -1254,7 +1258,18 @@ cherokee_connection_send_header (cherokee_connection_t *conn)
1254 1258
 	/* Send the buffer content
1255 1259
 	 */
1256 1260
 	ret = cherokee_socket_bufwrite (&conn->socket, &conn->buffer, &sent);
1257  
-	if (unlikely(ret != ret_ok)) return ret;
  1261
+	switch (ret) {
  1262
+	case ret_ok:
  1263
+		break;
  1264
+
  1265
+	case ret_eagain:
  1266
+		conn->polling_aim.fd   = conn->socket.socket;
  1267
+		conn->polling_aim.mode = poll_mode_write;
  1268
+		return ret_eagain;
  1269
+
  1270
+	default:
  1271
+		return ret;
  1272
+	}
1258 1273
 
1259 1274
 	/* Add to the connection traffic counter
1260 1275
 	 */
@@ -1340,8 +1355,12 @@ cherokee_connection_send (cherokee_connection_t *conn)
1340 1355
 			break;
1341 1356
 
1342 1357
 		case ret_eof:
  1358
+			return ret_eof;
  1359
+
1343 1360
 		case ret_eagain:
1344  
-			return ret;
  1361
+			conn->polling_aim.fd   = conn->socket.socket;
  1362
+			conn->polling_aim.mode = poll_mode_write;
  1363
+			return ret_eagain;
1345 1364
 
1346 1365
 		case ret_error:
1347 1366
 			conn->keepalive = 0;
@@ -1379,8 +1398,18 @@ cherokee_connection_send (cherokee_connection_t *conn)
1379 1398
 	}
1380 1399
 
1381 1400
 	ret = cherokee_socket_write (&conn->socket, conn->buffer.buf, to_send, &sent);
1382  
-	if (unlikely(ret != ret_ok))
  1401
+	switch (ret) {
  1402
+	case ret_ok:
  1403
+		break;
  1404
+
  1405
+	case ret_eagain:
  1406
+		conn->polling_aim.fd   = conn->socket.socket;
  1407
+		conn->polling_aim.mode = poll_mode_write;
  1408
+		return ret_eagain;
  1409
+
  1410
+	default:
1383 1411
 		return ret;
  1412
+	}
1384 1413
 
1385 1414
 	/* Drop out the sent info
1386 1415
 	 */
@@ -1523,12 +1552,17 @@ cherokee_connection_linger_read (cherokee_connection_t *conn)
1523 1552
 	cherokee_thread_t *thread   = CONN_THREAD(conn);
1524 1553
 	cherokee_buffer_t *tmp1     = THREAD_TMP_BUF1(thread);
1525 1554
 
1526  
-	TRACE(ENTRIES",linger", "Linger read, socket status %d\n", conn->socket.status);
  1555
+	TRACE(ENTRIES",linger", "Linger read, socket %s closed\n", conn->socket.closed ? "is" : "isn't");
1527 1556
 
1528 1557
 	while (true) {
1529 1558
 		/* Read from the socket to nowhere
1530 1559
 		 */
1531  
-		ret = cherokee_socket_read (&conn->socket, tmp1->buf, tmp1->size, &cnt_read);
  1560
+		ret = cherokee_socket_read (&conn->socket, tmp1->buf, tmp1->size - 1, &cnt_read);
  1561
+
  1562
+		if (cnt_read > 0) {
  1563
+			cherokee_buffer_clean (tmp1);
  1564
+		}
  1565
+
1532 1566
 		switch (ret) {
1533 1567
 		case ret_eof:
1534 1568
 			TRACE (ENTRIES",linger", "%s\n", "EOF");
@@ -1538,12 +1572,17 @@ cherokee_connection_linger_read (cherokee_connection_t *conn)
1538 1572
 			return ret_error;
1539 1573
 		case ret_eagain:
1540 1574
 			TRACE (ENTRIES",linger", "read %u, eagain\n", cnt_read);
  1575
+
  1576
+			conn->polling_aim.fd   = conn->socket.socket;
  1577
+			conn->polling_aim.mode = poll_mode_read;
1541 1578
 			return ret_eagain;
1542 1579
 		case ret_ok:
1543 1580
 			TRACE (ENTRIES",linger", "%u bytes tossed away\n", cnt_read);
  1581
+
1544 1582
 			retries--;
1545  
-			if (cnt_read == tmp1->size && retries > 0)
  1583
+			if ((cnt_read >= tmp1->size - 2) && (retries > 0))
1546 1584
 				continue;
  1585
+
1547 1586
 			return ret_eof;
1548 1587
 		default:
1549 1588
 			RET_UNKNOWN(ret);
@@ -2176,7 +2215,7 @@ cherokee_connection_get_request (cherokee_connection_t *conn)
2176 2215
 	 */
2177 2216
 	if (read_post)
2178 2217
 	{
2179  
-		ret = cherokee_post_read_header (&conn->post, conn);
  2218
+		ret = cherokee_post_read_header (&conn->post);
2180 2219
 		if (unlikely (ret != ret_ok)) {
2181 2220
 			return ret;
2182 2221
 		}
@@ -2858,8 +2897,6 @@ cherokee_connection_print (cherokee_connection_t *conn)
2858 2897
 		print_add (" tcp_cork");
2859 2898
 	if (conn->options & conn_op_document_root)
2860 2899
 		print_add (" document_root");
2861  
-	if (conn->options & conn_op_was_polling)
2862  
-		print_add (" was_polling");
2863 2900
 	if (conn->options & conn_op_cant_encoder)
2864 2901
 		print_add (" cant_encoder");
2865 2902
 	if (conn->options & conn_op_got_eof)
2  cherokee/connection_info.c
@@ -186,7 +186,7 @@ cherokee_connection_info_list_thread (cherokee_list_t    *list,
186 186
 
187 187
 	/* Does it has active connections?
188 188
 	 */
189  
-	if (thread->active_list_num <= 0)
  189
+	if (cherokee_list_empty (&thread->active_list))
190 190
 		return ret_not_found;
191 191
 
192 192
 	/* If it tries to adquire the thread ownership of the thread
6  cherokee/downloader_async.c
@@ -93,7 +93,7 @@ cherokee_downloader_async_connect (cherokee_downloader_async_t *adownloader)
93 93
 	ret = cherokee_fd_set_nonblocking (down->socket.socket, true);
94 94
 	if (ret != ret_ok) return ret;
95 95
 
96  
-	ret = cherokee_fdpoll_add (fdpoll, down->socket.socket, FDPOLL_MODE_WRITE);
  96
+	ret = cherokee_fdpoll_add (fdpoll, down->socket.socket, poll_mode_write);
97 97
 	if (ret != ret_ok) return ret;
98 98
 
99 99
 	adownloader->fd_added = down->socket.socket;
@@ -123,9 +123,9 @@ cherokee_downloader_async_step (cherokee_downloader_async_t *adownloader)
123 123
 	/* Check whether we are reading or writting
124 124
 	 */
125 125
 	if (down->phase <= downloader_phase_send_post)
126  
-		rw = FDPOLL_MODE_WRITE;
  126
+		rw = poll_mode_write;
127 127
 	else
128  
-		rw = FDPOLL_MODE_READ;
  128
+		rw = poll_mode_read;
129 129
 
130 130
 	TRACE(ENTRIES, "rw = %d\n", rw);
131 131
 
4  cherokee/error_list.py
@@ -904,10 +904,6 @@
904 904
 
905 905
 # cherokee/thread.c
906 906
 #
907  
-e('THREAD_RM_FD_POLL',
908  
-  title = "Could not remove fd(%d) from fdpoll",
909  
-  desc  = CODING_BUG)
910  
-
911 907
 e('THREAD_HANDLER_RET',
912 908
   title = "Unknown ret %d from handler %s",
913 909
   desc  = CODING_BUG)
75  cherokee/fdpoll-epoll.c
@@ -80,7 +80,7 @@ _free (cherokee_fdpoll_epoll_t *fdp)
80 80
 
81 81
 
82 82
 static ret_t
83  
-_add (cherokee_fdpoll_epoll_t *fdp, int fd, int rw)
  83
+_add (cherokee_fdpoll_epoll_t *fdp, int fd, int mode_rw)
84 84
 {
85 85
 	struct epoll_event ev;
86 86
 
@@ -94,16 +94,20 @@ _add (cherokee_fdpoll_epoll_t *fdp, int fd, int rw)
94 94
 	/* Add the new descriptor
95 95
 	 */
96 96
 	ev.data.u64 = 0;
97  
-	ev.data.fd = fd;
98  
-	switch (rw) {
99  
-	case FDPOLL_MODE_READ:
100  
-		ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;
101  
-		break;
102  
-	case FDPOLL_MODE_WRITE:
103  
-		ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP;
104  
-		break;
105  
-	default:
106  
-		ev.events = 0;
  97
+	ev.data.fd  = fd;
  98
+	ev.events   = 0;
  99
+
  100
+	/* Set mode
  101
+	 */
  102
+	if (mode_rw & poll_mode_read) {
  103
+		ev.events |= (EPOLLIN | EPOLLERR | EPOLLHUP);
  104
+	}
  105
+
  106
+	if (mode_rw & poll_mode_write) {
  107
+		ev.events |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
  108
+	}
  109
+
  110
+	if (unlikely (ev.events == 0)) {
107 111
 		SHOULDNT_HAPPEN;
108 112
 		return ret_error;
109 113
 	}
@@ -147,7 +151,7 @@ _del (cherokee_fdpoll_epoll_t *fdp, int fd)
147 151
 
148 152
 
149 153
 static int
150  
-_check (cherokee_fdpoll_epoll_t *fdp, int fd, int rw)
  154
+_check (cherokee_fdpoll_epoll_t *fdp, int fd, int rw_mode)
151 155
 {
152 156
 	int      fdidx;
153 157
 	uint32_t events;
@@ -181,14 +185,19 @@ _check (cherokee_fdpoll_epoll_t *fdp, int fd, int rw)
181 185
 	 */
182 186
 	events = fdp->ep_events[fdidx].events;
183 187
 
184  
-	switch (rw) {
185  
-	case FDPOLL_MODE_READ:
186  
-		return events & (EPOLLIN  | EPOLLERR | EPOLLHUP);
187  
-	case FDPOLL_MODE_WRITE:
188  
-		return events & (EPOLLOUT | EPOLLERR | EPOLLHUP);
189  
-	default:
190  
-		return -1;
  188
+	if ((rw_mode & poll_mode_read) && (events & EPOLLIN)) {
  189
+		return 1;
  190
+	}
  191
+
  192
+	if ((rw_mode & poll_mode_write) && (events & EPOLLOUT)) {
  193
+		return 1;
191 194
 	}
  195
+
  196
+	if (events & (EPOLLERR | EPOLLHUP)) {
  197
+		return 1;
  198
+	}
  199
+
  200
+	return -1;
192 201
 }
193 202
 
194 203
 
@@ -207,30 +216,36 @@ _reset (cherokee_fdpoll_epoll_t *fdp, int fd)
207 216
 
208 217
 
209 218
 static ret_t
210  
-_set_mode (cherokee_fdpoll_epoll_t *fdp, int fd, int rw)
  219
+_set_mode (cherokee_fdpoll_epoll_t *fdp, int fd, int rw_mode)
211 220
 {
212 221
 	struct epoll_event ev;
213 222
 
214 223
 	ev.data.u64 = 0;
215 224
 	ev.data.fd  = fd;
  225
+	ev.events   = 0;
216 226
 
217  
-	switch (rw) {
218  
-	case FDPOLL_MODE_READ:
219  
-		ev.events = EPOLLIN;
220  
-		break;
221  
-	case FDPOLL_MODE_WRITE:
222  
-		ev.events = EPOLLOUT;
223  
-		break;
224  
-	default:
225  
-		ev.events = 0;
  227
+	/* Set mode
  228
+	 */
  229
+	if (rw_mode & poll_mode_read) {
  230
+		ev.events |= (EPOLLIN | EPOLLERR | EPOLLHUP);
  231
+	}
  232
+
  233
+	if (rw_mode & poll_mode_write) {
  234
+		ev.events |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
  235
+	}
  236
+
  237
+	if (unlikely (ev.events == 0)) {
226 238
 		return ret_error;
227 239
 	}
228 240
 
229  
-	if (epoll_ctl(fdp->ep_fd, EPOLL_CTL_MOD, fd, &ev) < 0) {
  241
+	/* Apply it
  242
+	 */
  243
+	if (epoll_ctl (fdp->ep_fd, EPOLL_CTL_MOD, fd, &ev) < 0) {
230 244
 		LOG_ERRNO (errno, cherokee_err_error,
231 245
 			   CHEROKEE_ERROR_FDPOLL_EPOLL_CTL_MOD, fdp->ep_fd, fd);
232 246
 		return ret_error;
233 247
 	}
  248
+
234 249
 	return ret_ok;
235 250
 }
236 251
 
111  cherokee/fdpoll-kqueue.c
@@ -91,11 +91,15 @@ _free (cherokee_fdpoll_kqueue_t *fdp)
91 91
 
92 92
 
93 93
 static ret_t
94  
-_add_change(cherokee_fdpoll_kqueue_t *fdp, int fd, int rw, int change )
  94
+_add_change (cherokee_fdpoll_kqueue_t *fdp, int fd, int mode, int change)
95 95
 {
96 96
 	int            index;
97 97
 	struct kevent *event;
98 98
 
  99
+	/* The 'mode' variable should contain a single mode here. This
  100
+	 * function does not support multiple modes.
  101
+	 */
  102
+
99 103
 	index = fdp->nchanges;
100 104
 	if (unlikely (index >= FDPOLL(fdp)->nfiles)) {
101 105
 		PRINT_ERROR_S("kqueue_add: fdpoll is full !\n");
@@ -104,21 +108,23 @@ _add_change(cherokee_fdpoll_kqueue_t *fdp, int fd, int rw, int change )
104 108
 
105 109
 	event = &fdp->changelist[index];
106 110
 	event->ident = fd;
107  
-	switch (rw) {
108  
-	case FDPOLL_MODE_READ:
  111
+
  112
+	switch (mode) {
  113
+	case poll_mode_read:
109 114
 		event->filter = EVFILT_READ;
110 115
 		break;
111  
-	case FDPOLL_MODE_WRITE:
  116
+	case poll_mode_write:
112 117
 		event->filter = EVFILT_WRITE;
113 118
 		break;
114 119
 	default:
  120
+		event->filter = 0;
115 121
 		SHOULDNT_HAPPEN;
116  
-        }
  122
+	}
117 123
 
118 124
 	event->flags  = change;
119 125
 	event->fflags = 0;
120 126
 
121  
-	fdp->fdinterest[fd] = rw;
  127
+	fdp->fdinterest[fd] = mode;
122 128
 	fdp->nchanges++;
123 129
 
124 130
 	return ret_ok;
@@ -126,30 +132,55 @@ _add_change(cherokee_fdpoll_kqueue_t *fdp, int fd, int rw, int change )
126 132
 
127 133
 
128 134
 static ret_t
129  
-_add (cherokee_fdpoll_kqueue_t *fdp, int fd, int rw)
  135
+_add (cherokee_fdpoll_kqueue_t *fdp, int fd, int rw_mode)
130 136
 {
131  
-	int re;
  137
+	ret_t ret = ret_not_found;
  138
+
  139
+	if (rw_mode & poll_mode_read) {
  140
+		ret = _add_change (fdp, fd, poll_mode_read, EV_ADD);
  141
+		if (ret != ret_ok)
  142
+			return ret;
  143
+	}
132 144
 
133  
-	re = _add_change (fdp, fd, rw, EV_ADD);
134  
-	if (re == ret_ok) {
  145
+	if (rw_mode & poll_mode_write) {
  146
+		ret = _add_change (fdp, fd, poll_mode_write, EV_ADD);
  147
+		if (ret != ret_ok)
  148
+			return ret;
  149
+	}
  150
+
  151
+	if (ret == ret_ok) {
135 152
 		FDPOLL(fdp)->npollfds++;
136 153
 	}
137 154
 
138  
-	return re;
  155
+	return ret;
139 156
 }
140 157
 
141 158
 
142 159
 static ret_t
143 160
 _del (cherokee_fdpoll_kqueue_t *fdp, int fd)
144 161
 {
145  
-	int re;
  162
+	ret_t              ret      = ret_not_found;
  163
+	int                interest = fdp->fdinterest[fd];
  164
+	cherokee_boolean_t error    = false;
  165
+
  166
+	if (interest & poll_mode_read) {
  167
+		ret = _add_change (fdp, fd, poll_mode_read, EV_DELETE);
  168
+		if (ret != ret_ok)
  169
+			error = true;
  170
+	}
146 171
 
147  
-	re = _add_change (fdp, fd, fdp->fdinterest[fd], EV_DELETE);
148  
-	if (re == ret_ok) {
  172
+	if (interest & poll_mode_write) {
  173
+		ret = _add_change (fdp, fd, poll_mode_write, EV_DELETE);
  174
+		if (ret != ret_ok)
  175
+			error |= true;
  176
+	}
  177
+
  178
+	if ((ret == ret_ok) && (! error)) {
149 179
 		FDPOLL(fdp)->npollfds--;
150 180
 	}
151 181
 
152  
-	return re;
  182
+	fdp->fdinterest[fd] = 0;
  183
+	return ret;
153 184
 }
154 185
 
155 186
 
@@ -183,7 +214,7 @@ _watch (cherokee_fdpoll_kqueue_t *fdp, int timeout_msecs)
183 214
 		LOG_ERRNO (errno, cherokee_err_error, CHEROKEE_ERROR_FDPOLL_KQUEUE);
184 215
 		return 0;
185 216
 
186  
-	} else if (n_events > 0) {
  217
+	} else if (n_events >= 0) {
187 218
 		memset (fdp->fdevents, 0, FDPOLL(fdp)->system_nfiles * sizeof(int));
188 219
 
189 220
 		for (i = 0; i < n_events; ++i) {
@@ -207,7 +238,7 @@ _watch (cherokee_fdpoll_kqueue_t *fdp, int timeout_msecs)
207 238
 }
208 239
 
209 240
 static int
210  
-_check (cherokee_fdpoll_kqueue_t *fdp, int fd, int rw)
  241
+_check (cherokee_fdpoll_kqueue_t *fdp, int fd, int rw_mode)
211 242
 {
212 243
 	uint32_t events;
213 244
 
@@ -223,15 +254,16 @@ _check (cherokee_fdpoll_kqueue_t *fdp, int fd, int rw)
223 254
 		return 1;
224 255
 	}
225 256
 
226  
-	switch (rw) {
227  
-	case FDPOLL_MODE_READ:
228  
-		events &= KQUEUE_READ_EVENT;
229  
-		break;
230  
-	case FDPOLL_MODE_WRITE:
231  
-		events &= KQUEUE_WRITE_EVENT;
232  
-		break;
233  
-	default:
234  
-		SHOULDNT_HAPPEN;
  257
+	if ((rw_mode & poll_mode_read) &&
  258
+	    (events & KQUEUE_READ_EVENT))
  259
+	{
  260
+		return 1;
  261
+	}
  262
+
  263
+	if ((rw_mode & poll_mode_write) &&
  264
+	    (events & KQUEUE_WRITE_EVENT))
  265
+	{
  266
+		return 1;
235 267
 	}
236 268
 
237 269
 	return events;
@@ -249,24 +281,29 @@ _reset (cherokee_fdpoll_kqueue_t *fdp, int fd)
249 281
 
250 282
 
251 283
 static ret_t
252  
-_set_mode (cherokee_fdpoll_kqueue_t *fdp, int fd, int rw)
  284
+_set_mode (cherokee_fdpoll_kqueue_t *fdp, int fd, int rw_mode)
253 285
 {
254  
-	/* If transitioning from r -> w or from w -> r
255  
-	 * disable any active event on the fd as we are
256  
-	 * no longer interested on it.
  286
+	int prev_interest = fdp->fdinterest[fd];
  287
+
  288
+	/* If transitioning from R->W or from W->R disable any active
  289
+	 * event on the fd as we are no longer interested on it.
257 290
 	 */
258  
-	if ((rw == FDPOLL_MODE_WRITE) &&
259  
-	    (fdp->fdinterest[fd] == FDPOLL_MODE_READ))
  291
+
  292
+	/* No longer reading */
  293
+	if ((! (rw_mode & poll_mode_read)) &&
  294
+	    (prev_interest & poll_mode_read))
260 295
 	{
261  
-		_add_change (fdp, fd, FDPOLL_MODE_READ, EV_DELETE);
  296
+		_add_change (fdp, fd, poll_mode_read, EV_DELETE);
  297
+	}
262 298
 
263  
-	} else if ((rw == FDPOLL_MODE_READ) &&
264  
-		   (fdp->fdinterest[fd] == FDPOLL_MODE_WRITE))
  299
+	/* No longer writing */
  300
+	if ((! (rw_mode & poll_mode_write)) &&
  301
+	    (prev_interest & poll_mode_write))
265 302
 	{
266  
-		_add_change (fdp, fd, FDPOLL_MODE_WRITE, EV_DELETE);
  303
+		_add_change (fdp, fd, poll_mode_write, EV_DELETE);
267 304
 	}
268 305
 
269  
-	return _add_change (fdp, fd, rw, EV_ADD);
  306
+	return _add_change (fdp, fd, rw_mode, EV_ADD);
270 307
 }
271 308
 
272 309
 
86  cherokee/fdpoll-poll.c
@@ -32,7 +32,6 @@
32 32
 #define POLL_READ   (POLLIN  | POLL_ERROR)
33 33
 #define POLL_WRITE  (POLLOUT | POLL_ERROR)
34 34
 
35  
-
36 35
 /***********************************************************************/
37 36
 /* poll()                                                              */
38 37
 /*                                                                     */
@@ -68,9 +67,10 @@ _free (cherokee_fdpoll_poll_t *fdp)
68 67
 
69 68
 
70 69
 static ret_t
71  
-_add (cherokee_fdpoll_poll_t *fdp, int fd, int rw)
  70
+_add (cherokee_fdpoll_poll_t *fdp, int fd, int rw_mode)
72 71
 {
73  
-	cherokee_fdpoll_t *nfd = FDPOLL(fdp);
  72
+	short              events;
  73
+	cherokee_fdpoll_t *nfd     = FDPOLL(fdp);
74 74
 
75 75
 	/* Check the fd limit
76 76
 	 */
@@ -79,21 +79,20 @@ _add (cherokee_fdpoll_poll_t *fdp, int fd, int rw)
79 79
 		return ret_error;
80 80
 	}
81 81
 
  82
+	/* Translate mode */
  83
+	events = 0;
  84
+	if (rw_mode & poll_mode_read) {
  85
+		events |= POLLIN;
  86
+	}
  87
+	if (rw_mode & poll_mode_write) {
  88
+		events |= POLLOUT;
  89
+	}
  90
+
  91
+	/* Set values */
  92
+	fdp->pollfds[nfd->npollfds].events  = events;
82 93
 	fdp->pollfds[nfd->npollfds].fd      = fd;
83 94
 	fdp->pollfds[nfd->npollfds].revents = 0;
84 95
 
85  
-	switch (rw) {
86  
-	case FDPOLL_MODE_READ:
87  
-		fdp->pollfds[nfd->npollfds].events = POLLIN;
88  
-		break;
89  
-	case FDPOLL_MODE_WRITE:
90  
-		fdp->pollfds[nfd->npollfds].events = POLLOUT;
91  
-		break;
92  
-	default:
93  
-		SHOULDNT_HAPPEN;
94  
-		return ret_error;
95  
-	}
96  
-
97 96
 	fdp->fdidx[fd] = nfd->npollfds;
98 97
 	nfd->npollfds++;
99 98
 
@@ -102,9 +101,18 @@ _add (cherokee_fdpoll_poll_t *fdp, int fd, int rw)
102 101
 
103 102
 
104 103
 static ret_t
105  
-_set_mode (cherokee_fdpoll_poll_t *fdp, int fd, int rw)
  104
+_set_mode (cherokee_fdpoll_poll_t *fdp, int fd, int rw_mode)
106 105
 {
107  
-	fdp->pollfds[fdp->fdidx[fd]].events = (rw == FDPOLL_MODE_WRITE ? POLLOUT : POLLIN);
  106
+	short events = 0;
  107
+
  108
+	if (rw_mode & poll_mode_read) {
  109
+		events |= POLLIN;
  110
+	}
  111
+	if (rw_mode & poll_mode_write) {
  112
+		events |= POLLOUT;
  113
+	}
  114
+
  115
+	fdp->pollfds[fdp->fdidx[fd]].events = events;
108 116
 	return ret_ok;
109 117
 }
110 118
 
@@ -150,25 +158,30 @@ _del (cherokee_fdpoll_poll_t *fdp, int fd)
150 158
 
151 159
 
152 160
 static int
153  
-_check (cherokee_fdpoll_poll_t *fdp, int fd, int rw)
  161
+_check (cherokee_fdpoll_poll_t *fdp, int fd, int rw_mode)
154 162
 {
155 163
 	int revents;
156  
-	int idx = fdp->fdidx[fd];
  164
+	int idx      = fdp->fdidx[fd];
157 165
 
158 166
 	if (idx < 0 || idx >= FDPOLL(fdp)->nfiles)
159 167
 		return -1;
160 168
 
161 169
 	revents = fdp->pollfds[idx].revents;
162 170
 
163  
-	switch (rw) {
164  
-		case FDPOLL_MODE_READ:
165  
-			return revents & POLL_READ;
166  
-		case FDPOLL_MODE_WRITE:
167  
-			return revents & POLL_WRITE;
168  
-		default:
169  
-			SHOULDNT_HAPPEN;
170  
-			return -1;
  171
+	/* Actual result */
  172
+	if ((rw_mode & poll_mode_read) && (revents & POLLIN)) {
  173
+		return 1;
  174
+	}
  175
+	if ((rw_mode & poll_mode_write) && (revents & POLLOUT)) {
  176
+		return 1;
  177
+	}
  178
+
  179
+	/* Error */
  180
+	if (revents & (POLLERR|POLLHUP|POLLNVAL)) {
  181
+		return 1;
171 182
 	}
  183
+
  184
+	return 0;
172 185
 }
173 186
 
174 187
 
@@ -187,11 +200,28 @@ _reset (cherokee_fdpoll_poll_t *fdp, int fd)
187 200
 static int
188 201
 _watch (cherokee_fdpoll_poll_t *fdp, int timeout_msecs)
189 202
 {
  203
+	int re;
  204
+
190 205
 	if (unlikely (FDPOLL(fdp)->npollfds < 0)) {
191 206
 		SHOULDNT_HAPPEN;
192 207
 	}
193 208
 
194  
-	return poll (fdp->pollfds, FDPOLL(fdp)->npollfds, timeout_msecs);
  209
+	re = poll (fdp->pollfds, FDPOLL(fdp)->npollfds, timeout_msecs);
  210
+
  211
+#if 0
  212
+	{
  213
+		int                i;
  214
+		cherokee_fdpoll_t *nfd = FDPOLL(fdp);
  215
+
  216
+		printf ("total=%d = ", nfd->npollfds);
  217
+		for (i=0; i < nfd->npollfds; i++) {
  218
+			printf ("fd=%d[%d,%d], ", fdp->pollfds[i].fd, fdp->pollfds[i].events, fdp->pollfds[i].revents);
  219
+		}
  220
+		printf ("\n");
  221
+	}
  222
+#endif
  223
+
  224
+	return re;
195 225
 }
196 226
 
197 227
 
85  cherokee/fdpoll-port.c
@@ -32,9 +32,6 @@
32 32
 #include <unistd.h>
33 33
 #include <errno.h>
34 34
 
35  
-#define WRITE ""
36  
-#define READ  NULL
37  
-
38 35
 #define POLL_READ   (POLLIN)
39 36
 #define POLL_WRITE  (POLLOUT)
40 37
 #define POLL_ERROR  (POLLHUP | POLLERR | POLLNVAL)
@@ -70,16 +67,24 @@ typedef struct {
70 67
 
71 68
 
72 69
 static ret_t
73  
-fd_associate( cherokee_fdpoll_port_t *fdp, int fd, void *rw )
  70
+fd_associate (cherokee_fdpoll_port_t *fdp, int fd, void *rw_mode)
74 71
 {
75 72
 	int rc;
  73
+	int events = 0;
76 74
 
77  
-	rc = port_associate (fdp->port,                /* port */
78  
-	                     PORT_SOURCE_FD,           /* source */
79  
-	                     fd,                       /* object */
80  
-	                     rw?POLL_WRITE:POLL_READ,  /* events */
81  
-	                     rw);                      /* user data */
  75
+	if (*rw_mode & poll_mode_read) {
  76
+		events |= POLL_READ;
  77
+	}
82 78
 
  79
+	if (*rw_mode & poll_mode_write) {
  80
+		events |= POLL_WRITE;
  81
+	}
  82
+
  83
+	rc = port_associate (fdp->port,       /* port */
  84
+	                     PORT_SOURCE_FD,  /* source */
  85
+	                     fd,              /* object */
  86
+	                     events,          /* events */
  87
+	                     rw_mode);        /* user data */
83 88
 	if ( rc == -1 ) {
84 89
 		LOG_ERRNO (errno, cherokee_err_error,
85 90
 			   CHEROKEE_ERROR_FDPOLL_PORTS_ASSOCIATE, fd);
@@ -114,12 +119,12 @@ _free (cherokee_fdpoll_port_t *fdp)
114 119
 
115 120
 
116 121
 static ret_t
117  
-_add (cherokee_fdpoll_port_t *fdp, int fd, int rw)
  122
+_add (cherokee_fdpoll_port_t *fdp, int fd, int rw_mode)
118 123
 {
119 124
 	int rc;
120 125
 
121  
-	rc = fd_associate(fdp, fd, (rw == FDPOLL_MODE_WRITE ? WRITE : READ));
122  
-	if ( rc == -1 ) {
  126
+	rc = fd_associate (fdp, fd, rw_mode);
  127
+	if (rc == -1) {
123 128
 		LOG_ERRNO (errno, cherokee_err_error,
124 129
 			   CHEROKEE_ERROR_FDPOLL_PORTS_FD_ASSOCIATE, fd);
125 130
 		return ret_error;
@@ -212,27 +217,36 @@ _watch (cherokee_fdpoll_port_t *fdp, int timeout_msecs)
212 217
 
213 218
 
214 219
 static int
215  
-_check (cherokee_fdpoll_port_t *fdp, int fd, int rw)
  220
+_check (cherokee_fdpoll_port_t *fdp, int fd, int rw_mode)
216 221
 {
217  
-	uint32_t events;
  222
+	uint32_t events = 0;
218 223
 
219 224
 	/* Sanity check: is it a wrong fd?
220 225
 	 */
221  
-	if ( fd < 0 ) return -1;
  226
+	if (unlikely (fd < 0)) {
  227
+		return -1;
  228
+	}
222 229
 
223 230
 	events = fdp->port_activefd[fd];
224  
-	if ( events == -1 ) return 0;
225  
-
226  
-	switch (rw) {
227  
-	case FDPOLL_MODE_READ:
228  
-		events &= (POLL_READ | POLL_ERROR);
229  
-		break;
230  
-	case FDPOLL_MODE_WRITE:
231  
-		events &= (POLL_WRITE | POLL_ERROR);
232  
-		break;
  231
+	if (events == -1) {
  232
+		return 0;
  233
+	}
  234
+
  235
+	/* Check
  236
+	 */