summaryrefslogtreecommitdiff
path: root/ot_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_http.c')
-rw-r--r--ot_http.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/ot_http.c b/ot_http.c
index bb6ff24..602ff94 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -39,22 +39,30 @@ ssize_t g_stats_path_len;
39 39
40enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 }; 40enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 };
41 41
42int http_adopt(const int64_t sock, struct http_data *cookie) { 42struct http_data *http_adopt(const int64_t sock) {
43 struct http_data *heap = malloc(sizeof(*heap)); 43 struct http_data *cookie = fdstate_cookie(sock), *heap;
44 int interest;
44 45
45 if (!heap) 46 if (!cookie || !(cookie->flag & STRUCT_HTTP_FLAG_ONSTACK))
46 return -1; 47 return cookie;
48
49 if (!(heap = malloc(sizeof(*heap))))
50 return NULL;
47 51
48 *heap = *cookie; 52 *heap = *cookie;
49 heap->flag &= ~STRUCT_HTTP_FLAG_ONSTACK; 53 heap->flag &= ~STRUCT_HTTP_FLAG_ONSTACK;
54
55 /* Publishing the cookie is what lets another thread reach this connection,
56 so nothing may touch it afterwards, not even to read what it asked for */
57 interest = heap->interest;
50 fdstate_set_cookie((int)sock, heap); 58 fdstate_set_cookie((int)sock, heap);
51 59
52 if (event_add((int)sock, heap->interest, fdstate_generation((int)sock)) == -1) { 60 if (event_add((int)sock, interest, fdstate_generation((int)sock)) == -1) {
53 fdstate_set_cookie((int)sock, cookie); 61 fdstate_set_cookie((int)sock, cookie);
54 free(heap); 62 free(heap);
55 return -1; 63 return NULL;
56 } 64 }
57 return 0; 65 return heap;
58} 66}
59 67
60/* Give up a connection: the one place that knows everything hanging off it. */ 68/* Give up a connection: the one place that knows everything hanging off it. */
@@ -348,13 +356,17 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
348 } 356 }
349#endif 357#endif
350#endif 358#endif
351 /* Pass this task to the worker thread */
352 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; 359 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
353 360
354 /* Clients waiting for us should not easily timeout */ 361 /* Clients waiting for us should not easily timeout */
355 fdstate_set_expiry(sock, 0); 362 fdstate_set_expiry(sock, 0);
356 fullscrape_deliver(sock, format);
357 http_interest_set(sock, cookie, 0); 363 http_interest_set(sock, cookie, 0);
364
365 /* Everything this connection needs has been written, so it can be given
366 a home of its own and only then be made reachable by a worker thread */
367 if (!http_adopt(sock))
368 HTTPERROR_500;
369 fullscrape_deliver(sock, format);
358 return ws->reply_size = -2; 370 return ws->reply_size = -2;
359 } 371 }
360#endif 372#endif
@@ -366,6 +378,9 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
366 378
367 /* Complex stats also include expensive memory debugging tools */ 379 /* Complex stats also include expensive memory debugging tools */
368 fdstate_set_expiry(sock, 0); 380 fdstate_set_expiry(sock, 0);
381
382 if (!http_adopt(sock))
383 HTTPERROR_500;
369 stats_deliver(sock, mode); 384 stats_deliver(sock, mode);
370 return ws->reply_size = -2; 385 return ws->reply_size = -2;
371 } 386 }
@@ -448,8 +463,11 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *
448 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; 463 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
449 /* Clients waiting for us should not easily timeout */ 464 /* Clients waiting for us should not easily timeout */
450 fdstate_set_expiry(sock, 0); 465 fdstate_set_expiry(sock, 0);
451 fullscrape_deliver(sock, format);
452 http_interest_set(sock, cookie, 0); 466 http_interest_set(sock, cookie, 0);
467
468 if (!http_adopt(sock))
469 HTTPERROR_500;
470 fullscrape_deliver(sock, format);
453 return ws->reply_size = -2; 471 return ws->reply_size = -2;
454} 472}
455#endif 473#endif