summaryrefslogtreecommitdiff
path: root/ot_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_http.c')
-rw-r--r--ot_http.c53
1 files changed, 46 insertions, 7 deletions
diff --git a/ot_http.c b/ot_http.c
index 66f0102..602ff94 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -39,9 +39,33 @@ 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
42/* Give up a connection: the one place that knows everything hanging off it. 42struct http_data *http_adopt(const int64_t sock) {
43 The slot is released before anything is freed, so that a late event or the 43 struct http_data *cookie = fdstate_cookie(sock), *heap;
44 expiry sweep finds a closed descriptor rather than a freed cookie. */ 44 int interest;
45
46 if (!cookie || !(cookie->flag & STRUCT_HTTP_FLAG_ONSTACK))
47 return cookie;
48
49 if (!(heap = malloc(sizeof(*heap))))
50 return NULL;
51
52 *heap = *cookie;
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;
58 fdstate_set_cookie((int)sock, heap);
59
60 if (event_add((int)sock, interest, fdstate_generation((int)sock)) == -1) {
61 fdstate_set_cookie((int)sock, cookie);
62 free(heap);
63 return NULL;
64 }
65 return heap;
66}
67
68/* Give up a connection: the one place that knows everything hanging off it. */
45void http_close(const int64_t sock) { 69void http_close(const int64_t sock) {
46 struct http_data *cookie = fdstate_cookie(sock); 70 struct http_data *cookie = fdstate_cookie(sock);
47 71
@@ -54,7 +78,8 @@ void http_close(const int64_t sock) {
54 buf_reset(&cookie->request); 78 buf_reset(&cookie->request);
55 if (cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)) 79 if (cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER))
56 mutex_workqueue_canceltask(sock); 80 mutex_workqueue_canceltask(sock);
57 free(cookie); 81 if (!(cookie->flag & STRUCT_HTTP_FLAG_ONSTACK))
82 free(cookie);
58 } 83 }
59 84
60 event_close((int)sock); 85 event_close((int)sock);
@@ -140,6 +165,10 @@ void http_interest_set(const int64_t sock, struct http_data *cookie, int what) {
140 if (cookie->interest == what) 165 if (cookie->interest == what)
141 return; 166 return;
142 cookie->interest = what; 167 cookie->interest = what;
168 /* Still on a stack, so not in the event loop yet: whoever adopts this
169 connection registers whatever it asked for last */
170 if (cookie->flag & STRUCT_HTTP_FLAG_ONSTACK)
171 return;
143 event_modify((int)sock, what, fdstate_generation((int)sock)); 172 event_modify((int)sock, what, fdstate_generation((int)sock));
144} 173}
145 174
@@ -327,13 +356,17 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
327 } 356 }
328#endif 357#endif
329#endif 358#endif
330 /* Pass this task to the worker thread */
331 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; 359 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
332 360
333 /* Clients waiting for us should not easily timeout */ 361 /* Clients waiting for us should not easily timeout */
334 fdstate_set_expiry(sock, 0); 362 fdstate_set_expiry(sock, 0);
335 fullscrape_deliver(sock, format);
336 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);
337 return ws->reply_size = -2; 370 return ws->reply_size = -2;
338 } 371 }
339#endif 372#endif
@@ -345,6 +378,9 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
345 378
346 /* Complex stats also include expensive memory debugging tools */ 379 /* Complex stats also include expensive memory debugging tools */
347 fdstate_set_expiry(sock, 0); 380 fdstate_set_expiry(sock, 0);
381
382 if (!http_adopt(sock))
383 HTTPERROR_500;
348 stats_deliver(sock, mode); 384 stats_deliver(sock, mode);
349 return ws->reply_size = -2; 385 return ws->reply_size = -2;
350 } 386 }
@@ -427,8 +463,11 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *
427 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; 463 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
428 /* Clients waiting for us should not easily timeout */ 464 /* Clients waiting for us should not easily timeout */
429 fdstate_set_expiry(sock, 0); 465 fdstate_set_expiry(sock, 0);
430 fullscrape_deliver(sock, format);
431 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);
432 return ws->reply_size = -2; 471 return ws->reply_size = -2;
433} 472}
434#endif 473#endif