summaryrefslogtreecommitdiff
path: root/ot_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_http.c')
-rw-r--r--ot_http.c56
1 files changed, 48 insertions, 8 deletions
diff --git a/ot_http.c b/ot_http.c
index 66f0102..b0e1de3 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -22,6 +22,7 @@
22#include "ot_iovec.h" 22#include "ot_iovec.h"
23#include "ot_ip.h" 23#include "ot_ip.h"
24#include "ot_mutex.h" 24#include "ot_mutex.h"
25#include "ot_workqueue.h"
25#include "ot_scan.h" 26#include "ot_scan.h"
26#include "ot_event.h" 27#include "ot_event.h"
27#include "ot_fdstate.h" 28#include "ot_fdstate.h"
@@ -39,9 +40,33 @@ ssize_t g_stats_path_len;
39 40
40enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 }; 41enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 };
41 42
42/* Give up a connection: the one place that knows everything hanging off it. 43struct http_data *http_adopt(const int64_t sock) {
43 The slot is released before anything is freed, so that a late event or the 44 struct http_data *cookie = fdstate_cookie(sock), *heap;
44 expiry sweep finds a closed descriptor rather than a freed cookie. */ 45 int interest;
46
47 if (!cookie || !(cookie->flag & STRUCT_HTTP_FLAG_ONSTACK))
48 return cookie;
49
50 if (!(heap = malloc(sizeof(*heap))))
51 return NULL;
52
53 *heap = *cookie;
54 heap->flag &= ~STRUCT_HTTP_FLAG_ONSTACK;
55
56 /* Publishing the cookie is what lets another thread reach this connection,
57 so nothing may touch it afterwards, not even to read what it asked for */
58 interest = heap->interest;
59 fdstate_set_cookie((int)sock, heap);
60
61 if (event_add((int)sock, interest, fdstate_generation((int)sock)) == -1) {
62 fdstate_set_cookie((int)sock, cookie);
63 free(heap);
64 return NULL;
65 }
66 return heap;
67}
68
69/* Give up a connection: the one place that knows everything hanging off it. */
45void http_close(const int64_t sock) { 70void http_close(const int64_t sock) {
46 struct http_data *cookie = fdstate_cookie(sock); 71 struct http_data *cookie = fdstate_cookie(sock);
47 72
@@ -53,8 +78,9 @@ void http_close(const int64_t sock) {
53 free(cookie->batch); 78 free(cookie->batch);
54 buf_reset(&cookie->request); 79 buf_reset(&cookie->request);
55 if (cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)) 80 if (cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER))
56 mutex_workqueue_canceltask(sock); 81 workqueue_canceltask(sock);
57 free(cookie); 82 if (!(cookie->flag & STRUCT_HTTP_FLAG_ONSTACK))
83 free(cookie);
58 } 84 }
59 85
60 event_close((int)sock); 86 event_close((int)sock);
@@ -140,6 +166,10 @@ void http_interest_set(const int64_t sock, struct http_data *cookie, int what) {
140 if (cookie->interest == what) 166 if (cookie->interest == what)
141 return; 167 return;
142 cookie->interest = what; 168 cookie->interest = what;
169 /* Still on a stack, so not in the event loop yet: whoever adopts this
170 connection registers whatever it asked for last */
171 if (cookie->flag & STRUCT_HTTP_FLAG_ONSTACK)
172 return;
143 event_modify((int)sock, what, fdstate_generation((int)sock)); 173 event_modify((int)sock, what, fdstate_generation((int)sock));
144} 174}
145 175
@@ -327,13 +357,17 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
327 } 357 }
328#endif 358#endif
329#endif 359#endif
330 /* Pass this task to the worker thread */
331 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; 360 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
332 361
333 /* Clients waiting for us should not easily timeout */ 362 /* Clients waiting for us should not easily timeout */
334 fdstate_set_expiry(sock, 0); 363 fdstate_set_expiry(sock, 0);
335 fullscrape_deliver(sock, format);
336 http_interest_set(sock, cookie, 0); 364 http_interest_set(sock, cookie, 0);
365
366 /* Everything this connection needs has been written, so it can be given
367 a home of its own and only then be made reachable by a worker thread */
368 if (!http_adopt(sock))
369 HTTPERROR_500;
370 fullscrape_deliver(sock, format);
337 return ws->reply_size = -2; 371 return ws->reply_size = -2;
338 } 372 }
339#endif 373#endif
@@ -345,6 +379,9 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
345 379
346 /* Complex stats also include expensive memory debugging tools */ 380 /* Complex stats also include expensive memory debugging tools */
347 fdstate_set_expiry(sock, 0); 381 fdstate_set_expiry(sock, 0);
382
383 if (!http_adopt(sock))
384 HTTPERROR_500;
348 stats_deliver(sock, mode); 385 stats_deliver(sock, mode);
349 return ws->reply_size = -2; 386 return ws->reply_size = -2;
350 } 387 }
@@ -427,8 +464,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; 464 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
428 /* Clients waiting for us should not easily timeout */ 465 /* Clients waiting for us should not easily timeout */
429 fdstate_set_expiry(sock, 0); 466 fdstate_set_expiry(sock, 0);
430 fullscrape_deliver(sock, format);
431 http_interest_set(sock, cookie, 0); 467 http_interest_set(sock, cookie, 0);
468
469 if (!http_adopt(sock))
470 HTTPERROR_500;
471 fullscrape_deliver(sock, format);
432 return ws->reply_size = -2; 472 return ws->reply_size = -2;
433} 473}
434#endif 474#endif