Commit Diff


commit - 0d8d489a9ef3cda200d0e71337bc1b6d1c7bc03f
commit + cb8b898671a36b65caec01bef948f24df2a3c3a8
blob - 6037bbba2a23ca1e59d0c1a0109c442fbe0595a5
blob + 2fc28dbf71ef0e110ace7352fe04fa4512d98e2d
--- gotwebd/fcgi.c
+++ gotwebd/fcgi.c
@@ -352,7 +352,8 @@ fcgi_send_response(struct request *c, struct fcgi_resp
 {
 	struct fcgi_record_header *header;
 	struct timespec ts;
-	size_t padded_len;
+	size_t padded_len, off;
+	ssize_t nw;
 	int err = 0, th = 2000;
 
 	ts.tv_sec = 0;
@@ -378,14 +379,27 @@ fcgi_send_response(struct request *c, struct fcgi_resp
 	 * disconnect. Let's at least try to write the data a few times before
 	 * giving up.
 	 */
-	while ((write(c->fd, resp->data + resp->data_pos,
-	    resp->data_len)) == -1) {
-		nanosleep(&ts, NULL);
-		err++;
-		if (err == th) {
+	for (off = 0; off < resp->data_len; off += nw) {
+		nw = write(c->fd, resp->data + off, resp->data_len - off);
+		if (nw == 0) {
+			c->sock->client_status = CLIENT_DISCONNECT;
+			break;
+		}
+		if (nw == -1) {
+			err++;
+			if (errno == EAGAIN && err < th) {
+				nw = 0;
+				nanosleep(&ts, NULL);
+				continue;
+			}
+			log_warn("write");
 			c->sock->client_status = CLIENT_DISCONNECT;
 			break;
 		}
+
+		if (nw != resp->data_len - off)
+			log_debug("partial write: %zu vs %zu", nw,
+			    resp->data_len - off);
 	}
 
 	free(resp);