From c1edca2a427dc1ff402866e11875c804a0df6155 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Thu, 13 Aug 2020 19:27:35 -0400 Subject: [PATCH] chore: assorted socket error handling --- runtime/include/runtime.h | 13 ++++++---- runtime/src/runtime.c | 51 ++++++++++++++++++++++++++------------- runtime/src/sandbox.c | 13 +++++----- 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/runtime/include/runtime.h b/runtime/include/runtime.h index 485858c..1af6ada 100644 --- a/runtime/include/runtime.h +++ b/runtime/include/runtime.h @@ -12,7 +12,7 @@ #endif #define LISTENER_THREAD_CORE_ID 0 /* Dedicated Listener Core */ -#define LISTENER_THREAD_MAX_EPOLL_EVENTS 1024 +#define LISTENER_THREAD_MAX_EPOLL_EVENTS 2048 #define RUNTIME_LOG_FILE "awesome.log" #define RUNTIME_MAX_SANDBOX_REQUEST_COUNT (1 << 19) /* random! */ @@ -83,9 +83,12 @@ runtime_is_worker() static inline void runtime_log_requests_responses() { - debuglog("Requests: %u\n2XX: %u\n4XX: %u\n5XX: %u\nOutstanding Requests: %u\n", runtime_total_requests, - runtime_total_2XX_responses, runtime_total_4XX_responses, runtime_total_5XX_responses, - runtime_total_requests - runtime_total_2XX_responses - runtime_total_4XX_responses - - runtime_total_5XX_responses); + int64_t total_responses = runtime_total_2XX_responses + runtime_total_4XX_responses + + runtime_total_5XX_responses; + int64_t outstanding_requests = (int64_t)runtime_total_requests - total_responses; + + debuglog("Requests: %u (%ld outstanding)\n\tResponses: %ld\n\t\t2XX: %u\n\t\t4XX: %u\n\t\t5XX: %u\n", + runtime_total_requests, outstanding_requests, total_responses, runtime_total_2XX_responses, + runtime_total_4XX_responses, runtime_total_5XX_responses); }; #endif diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index 49770a9..310f674 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -73,14 +73,14 @@ runtime_initialize(void) /** * Rejects Requests as determined by admissions control - * @param socket_descriptor - the client we are rejecting + * @param client_socket - the client we are rejecting */ static inline void -listener_thread_reject(int socket_descriptor) +listener_thread_reject(int client_socket) { - assert(socket_descriptor >= 0); + assert(client_socket >= 0); - int send_rc = send(socket_descriptor, HTTP_RESPONSE_504_SERVICE_UNAVAILABLE, + int send_rc = send(client_socket, HTTP_RESPONSE_504_SERVICE_UNAVAILABLE, strlen(HTTP_RESPONSE_504_SERVICE_UNAVAILABLE), 0); if (send_rc < 0) goto send_504_err; @@ -90,7 +90,7 @@ listener_thread_reject(int socket_descriptor) #endif close: - if (close(socket_descriptor) < 0) panic("Error closing client socket - %s", strerror(errno)); + if (close(client_socket) < 0) panic("Error closing client socket - %s", strerror(errno)); return; send_504_err: debuglog("Error sending 504: %s", strerror(errno)); @@ -116,31 +116,48 @@ listener_thread_main(void *dummy) while (true) { int request_count = epoll_wait(runtime_epoll_file_descriptor, epoll_events, LISTENER_THREAD_MAX_EPOLL_EVENTS, -1); + if (request_count < 0) panic("epoll_wait: %s", strerror(errno)); + if (request_count == 0) panic("Unexpectedly returned with epoll_wait timeout not set\n"); /* Capture Start Time to calculate absolute deadline */ uint64_t request_arrival_timestamp = __getcycles(); for (int i = 0; i < request_count; i++) { - if (epoll_events[i].events & EPOLLERR) { - perror("epoll_wait"); - assert(false); - } + if (epoll_events[i].events & EPOLLERR) panic("epoll_wait: %s", strerror(errno)); /* Accept Client Request */ struct sockaddr_in client_address; socklen_t client_length = sizeof(client_address); struct module * module = (struct module *)epoll_events[i].data.ptr; assert(module); - int es = module->socket_descriptor; - int socket_descriptor = accept(es, (struct sockaddr *)&client_address, &client_length); - if (socket_descriptor < 0) { - perror("accept"); - assert(false); - } + int server_socket = module->socket_descriptor; + int client_socket = accept(server_socket, (struct sockaddr *)&client_address, &client_length); + if (client_socket < 0) panic("accept: %s", strerror(errno)); + #ifdef LOG_TOTAL_REQS_RESPS runtime_total_requests++; runtime_log_requests_responses(); #endif + /* Peek to ensure the socket isn't empty. Return 400 and close if empty */ + char peek_buffer[10]; + int bytes = recv(client_socket, &peek_buffer, 9, MSG_PEEK); + if (bytes < 0) panic("Peek: %s\n", strerror(errno)); + if (bytes == 0) { + send(client_socket, HTTP_RESPONSE_400_BAD_REQUEST, + strlen(HTTP_RESPONSE_400_BAD_REQUEST), 0); + if (close(client_socket) < 0) { + panic("Error closing client socket - %s", strerror(errno)); + } + +#ifdef LOG_TOTAL_REQS_RESPS + runtime_total_4XX_responses++; + debuglog("Listener Core rejected empty request\n"); + runtime_log_requests_responses(); +#endif + /* Advance in for loop to next socket */ + continue; + }; + /* Perform Admission Control */ uint32_t estimated_execution = perf_window_get_percentile(&module->perf_window, 0.5); @@ -153,13 +170,13 @@ listener_thread_main(void *dummy) double admissions_estimate = (double)estimated_execution / module->relative_deadline; if (runtime_admitted + admissions_estimate >= runtime_worker_threads_count) { - listener_thread_reject(socket_descriptor); + listener_thread_reject(client_socket); continue; } /* Allocate a Sandbox Request */ struct sandbox_request *sandbox_request = - sandbox_request_allocate(module, module->name, socket_descriptor, + sandbox_request_allocate(module, module->name, client_socket, (const struct sockaddr *)&client_address, request_arrival_timestamp, admissions_estimate); diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index 1dc52cf..1f006ff 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -74,14 +74,15 @@ static inline int sandbox_receive_and_parse_client_request(struct sandbox *sandbox) { assert(sandbox != NULL); - - sandbox->request_response_data_length = 0; + assert(sandbox->module->max_request_size > 0); + assert(sandbox->request_response_data_length == 0); #ifndef USE_HTTP_UVIO int r = 0; - r = recv(sandbox->client_socket_descriptor, (sandbox->request_response_data), sandbox->module->max_request_size, + r = recv(sandbox->client_socket_descriptor, sandbox->request_response_data, sandbox->module->max_request_size, 0); + if (r == 0) debuglog("Socket %d returned 0 bytes\n", sandbox->client_socket_descriptor); if (r < 0) { - debuglog("Error reading request data from client socket - %s", strerror(errno)); + debuglog("Error reading socket %d - %s\n", sandbox->client_socket_descriptor, strerror(errno)); return r; } while (r > 0) { @@ -94,7 +95,7 @@ sandbox_receive_and_parse_client_request(struct sandbox *sandbox) (sandbox->request_response_data + sandbox->request_response_data_length), sandbox->module->max_request_size - sandbox->request_response_data_length, 0); if (r < 0) { - debuglog("Error reading request data from client socket - %s", strerror(errno)); + debuglog("Error reading socket %d - %s\n", sandbox->client_socket_descriptor, strerror(errno)); return r; } } @@ -105,7 +106,7 @@ sandbox_receive_and_parse_client_request(struct sandbox *sandbox) worker_thread_process_io(); #endif if (sandbox->request_response_data_length == 0) { - debuglog("request_response_data_length was unexpectedly 0"); + debuglog("request_response_data_length was unexpectedly 0\n"); return 0; } sandbox->request_length = sandbox->request_response_data_length;