summaryrefslogtreecommitdiff
path: root/ot_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_http.c')
-rw-r--r--ot_http.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/ot_http.c b/ot_http.c
index bb6ff24..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,22 +40,30 @@ 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
42int http_adopt(const int64_t sock, struct http_data *cookie) { 43struct http_data *http_adopt(const int64_t sock) {
43 struct http_data *heap = malloc(sizeof(*heap)); 44 struct http_data *cookie = fdstate_cookie(sock), *heap;
45 int interest;
44 46
45 if (!heap) 47 if (!cookie || !(cookie->flag & STRUCT_HTTP_FLAG_ONSTACK))
46 return -1; 48 return cookie;
49
50 if (!(heap = malloc(sizeof(*heap))))
51 return NULL;
47 52
48 *heap = *cookie; 53 *heap = *cookie;
49 heap->flag &= ~STRUCT_HTTP_FLAG_ONSTACK; 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;
50 fdstate_set_cookie((int)sock, heap); 59 fdstate_set_cookie((int)sock, heap);
51 60
52 if (event_add((int)sock, heap->interest, fdstate_generation((int)sock)) == -1) { 61 if (event_add((int)sock, interest, fdstate_generation((int)sock)) == -1) {
53 fdstate_set_cookie((int)sock, cookie); 62 fdstate_set_cookie((int)sock, cookie);
54 free(heap); 63 free(heap);
55 return -1; 64 return NULL;
56 } 65 }
57 return 0; 66 return heap;
58} 67}
59 68
60/* Give up a connection: the one place that knows everything hanging off it. */ 69/* Give up a connection: the one place that knows everything hanging off it. */
@@ -69,7 +78,7 @@ void http_close(const int64_t sock) {
69 free(cookie->batch); 78 free(cookie->batch);
70 buf_reset(&cookie->request); 79 buf_reset(&cookie->request);
71 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))
72 mutex_workqueue_canceltask(sock); 81 workqueue_canceltask(sock);
73 if (!(cookie->flag & STRUCT_HTTP_FLAG_ONSTACK)) 82 if (!(cookie->flag & STRUCT_HTTP_FLAG_ONSTACK))
74 free(cookie); 83 free(cookie);
75 } 84 }
@@ -348,13 +357,17 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
348 } 357 }
349#endif 358#endif
350#endif 359#endif
351 /* Pass this task to the worker thread */
352 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; 360 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
353 361
354 /* Clients waiting for us should not easily timeout */ 362 /* Clients waiting for us should not easily timeout */
355 fdstate_set_expiry(sock, 0); 363 fdstate_set_expiry(sock, 0);
356 fullscrape_deliver(sock, format);
357 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);
358 return ws->reply_size = -2; 371 return ws->reply_size = -2;
359 } 372 }
360#endif 373#endif
@@ -366,6 +379,9 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
366 379
367 /* Complex stats also include expensive memory debugging tools */ 380 /* Complex stats also include expensive memory debugging tools */
368 fdstate_set_expiry(sock, 0); 381 fdstate_set_expiry(sock, 0);
382
383 if (!http_adopt(sock))
384 HTTPERROR_500;
369 stats_deliver(sock, mode); 385 stats_deliver(sock, mode);
370 return ws->reply_size = -2; 386 return ws->reply_size = -2;
371 } 387 }
@@ -448,8 +464,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; 464 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
449 /* Clients waiting for us should not easily timeout */ 465 /* Clients waiting for us should not easily timeout */
450 fdstate_set_expiry(sock, 0); 466 fdstate_set_expiry(sock, 0);
451 fullscrape_deliver(sock, format);
452 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);
453 return ws->reply_size = -2; 472 return ws->reply_size = -2;
454} 473}
455#endif 474#endif