Browse code

- fixes: - on io_watch_add overwrite error don't delete the previous fd hash entry + more error debugging info - return proper len on pending connect (instead of -1) - tcp_reader: always check if a connection was marked as bad and if so release it immediately + error checks for io_watch_*

Andrei Pelinescu-Onciul authored on 21/12/2007 23:27:13
Showing 3 changed files
... ...
@@ -344,8 +344,9 @@ inline static int io_watch_add(	io_wait_h* h,
344 344
 	e=get_fd_map(h, fd);
345 345
 	if (unlikely(e && (e->type!=0 /*F_NONE*/))){
346 346
 		LOG(L_ERR, "ERROR: io_watch_add: trying to overwrite entry %d"
347
-				" in the hash(%d, %d, %p) with (%d, %d, %p)\n",
348
-				fd, e->fd, e->type, e->data, fd, type, data);
347
+				" watched for %x in the hash(%d, %d, %p) with (%d, %d, %p)\n",
348
+				fd, events, e->fd, e->type, e->data, fd, type, data);
349
+		e=0;
349 350
 		goto error;
350 351
 	}
351 352
 	
... ...
@@ -442,6 +443,11 @@ again2:
442 442
 			}
443 443
 			if (unlikely( events & POLLOUT)){
444 444
 				if (unlikely(kq_ev_change(h, fd, EVFILT_WRITE, EV_ADD, e)==-1))
445
+				{
446
+					if (likely(events & POLLIN)){
447
+						kq_ev_change(h, fd, EVFILT_READ, EV_DELETE, 0);
448
+					}
449
+				}
445 450
 				goto error;
446 451
 			}
447 452
 			break;
... ...
@@ -554,8 +560,8 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
554 554
 	}
555 555
 	if (unlikely(e->type==0 /*F_NONE*/)){
556 556
 		LOG(L_ERR, "ERROR: io_watch_del: trying to delete already erased"
557
-				" entry %d in the hash(%d, %d, %p) )\n",
558
-				fd, e->fd, e->type, e->data);
557
+				" entry %d in the hash(%d, %d, %p) flags %x)\n",
558
+				fd, e->fd, e->type, e->data, flags);
559 559
 		goto error;
560 560
 	}
561 561
 	events=e->events;
... ...
@@ -1566,6 +1566,7 @@ no_id:
1566 1566
 										c, strerror(errno), errno);
1567 1567
 							goto conn_wait_error;
1568 1568
 						}
1569
+						n=len;
1569 1570
 						goto end;
1570 1571
 					}
1571 1572
 					/* error: destroy it directly */
... ...
@@ -697,7 +697,10 @@ static ticks_t tcpconn_read_timeout(ticks_t t, struct timer_ln* tl, void* data)
697 697
 		return (ticks_t)(c->timeout - t);
698 698
 	}
699 699
 	/* if conn->state is ERROR or BAD => force timeout too */
700
-	io_watch_del(&io_w, c->fd, -1, IO_FD_CLOSING);
700
+	if (unlikely(io_watch_del(&io_w, c->fd, -1, IO_FD_CLOSING)<0)){
701
+		LOG(L_ERR, "ERROR; tcpconn_read_timeout: io_watch_del failed for %p"
702
+					" id %d fd %d, state %d\n", c, c->id, c->fd, c->state);
703
+	}
701 704
 	tcpconn_listrm(tcp_conn_lst, c, c_next, c_prev);
702 705
 	release_tcpconn(c, (c->state<0)?CONN_ERROR:CONN_RELEASE, tcpmain_sock);
703 706
 	
... ...
@@ -767,9 +770,15 @@ again:
767 767
 							" connection received: %p, id %d, fd %d, refcnt %d"
768 768
 							" state %d (n=%d)\n", con, con->id, con->fd,
769 769
 							atomic_get(&con->refcnt), con->state, n);
770
-				release_tcpconn(con, CONN_ERROR, tcpmain_sock);
770
+				goto con_error;
771 771
 				break; /* try to recover */
772 772
 			}
773
+			if (unlikely(con->state==S_CONN_BAD)){
774
+				LOG(L_WARN, "WARNING: tcp_receive: handle_io: received an"
775
+							" already bad connection: %p id %d refcnt %d\n",
776
+							con, con->id, atomic_get(&con->refcnt));
777
+				goto con_error;
778
+			}
773 779
 			/* must be before io_watch_add, io_watch_add might catch some
774 780
 			 * already existing events => might call handle_io and
775 781
 			 * handle_io might decide to del. the new connection =>
... ...
@@ -783,8 +792,9 @@ again:
783 783
 			local_timer_add(&tcp_reader_ltimer, &con->timer,
784 784
 								S_TO_TICKS(TCP_CHILD_TIMEOUT), t);
785 785
 			if (unlikely(io_watch_add(&io_w, s, POLLIN, F_TCPCONN, con))<0){
786
-				LOG(L_CRIT, "ERROR: tcp_receive: handle_io: failed to add"
787
-						" new socket to the fd list\n");
786
+				LOG(L_CRIT, "ERROR; tcpconn_receive: handle_io: io_watch_add "
787
+							"failed for %p id %d fd %d, state %d\n",
788
+							con, con->id, con->fd, con->state);
788 789
 				tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
789 790
 				local_timer_del(&tcp_reader_ltimer, &con->timer);
790 791
 				goto con_error;
... ...
@@ -792,10 +802,23 @@ again:
792 792
 			break;
793 793
 		case F_TCPCONN:
794 794
 			con=(struct tcp_connection*)fm->data;
795
+			if (unlikely(con->state==S_CONN_BAD)){
796
+				resp=CONN_ERROR;
797
+				LOG(L_WARN, "WARNING: tcp_receive: handle_io: F_TCPCONN"
798
+							" connection marked as bad: %p id %d refcnt %d\n",
799
+							con, con->id, atomic_get(&con->refcnt));
800
+				goto read_error;
801
+			}
795 802
 			resp=tcp_read_req(con, &ret);
796 803
 			if (unlikely(resp<0)){
804
+read_error:
797 805
 				ret=-1; /* some error occured */
798
-				io_watch_del(&io_w, con->fd, idx, IO_FD_CLOSING);
806
+				if (unlikely(io_watch_del(&io_w, con->fd, idx,
807
+											IO_FD_CLOSING) < 0)){
808
+				LOG(L_CRIT, "ERROR; tcpconn_receive: handle_io: io_watch_del "
809
+							"failed for %p id %d fd %d, state %d\n",
810
+							con, con->id, con->fd, con->state);
811
+				}
799 812
 				tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
800 813
 				local_timer_del(&tcp_reader_ltimer, &con->timer);
801 814
 				con->state=S_CONN_BAD;
... ...
@@ -818,7 +841,7 @@ again:
818 818
 	return ret;
819 819
 con_error:
820 820
 	con->state=S_CONN_BAD;
821
-	release_tcpconn(con, CONN_ERROR, fm->fd);
821
+	release_tcpconn(con, CONN_ERROR, tcpmain_sock);
822 822
 	return ret;
823 823
 error:
824 824
 	return -1;