Skip to content

Commit 0533382

Browse files
committed
Respond with HTTP_UNAVAILABLE if coro_malloc() fails
1 parent a842cb2 commit 0533382

File tree

1 file changed

+95
-79
lines changed

1 file changed

+95
-79
lines changed

src/lib/lwan-thread.c

+95-79
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,85 @@ static bool lwan_setup_tls(const struct lwan *l, struct lwan_connection *conn)
360360
}
361361
#endif
362362

363+
__attribute__((cold))
364+
static bool send_buffer_without_coro(int fd, const char *buf, size_t buf_len, int flags)
365+
{
366+
size_t total_sent = 0;
367+
368+
for (int try = 0; try < 10; try++) {
369+
size_t to_send = buf_len - total_sent;
370+
if (!to_send)
371+
return true;
372+
373+
ssize_t sent = send(fd, buf + total_sent, to_send, flags);
374+
if (sent <= 0) {
375+
if (errno == EINTR)
376+
continue;
377+
if (errno == EAGAIN)
378+
continue;
379+
break;
380+
}
381+
382+
total_sent += (size_t)sent;
383+
}
384+
385+
return false;
386+
}
387+
388+
__attribute__((cold))
389+
static bool send_string_without_coro(int fd, const char *str, int flags)
390+
{
391+
return send_buffer_without_coro(fd, str, strlen(str), flags);
392+
}
393+
394+
__attribute__((cold)) static void
395+
send_last_response_without_coro(const struct lwan *l,
396+
const struct lwan_connection *conn,
397+
enum lwan_http_status status)
398+
{
399+
int fd = lwan_connection_get_fd(l, conn);
400+
401+
if (conn->flags & CONN_TLS) {
402+
/* There's nothing that can be done here if a client is expecting a
403+
* TLS connection: the TLS handshake requires a coroutine as it
404+
* might yield. (In addition, the TLS handshake might allocate
405+
* memory, and if you couldn't create a coroutine at this point,
406+
* it's unlikely you'd be able to allocate memory for the TLS
407+
* context anyway.) */
408+
goto shutdown_and_close;
409+
}
410+
411+
if (!send_string_without_coro(fd, "HTTP/1.0 ", MSG_MORE))
412+
goto shutdown_and_close;
413+
414+
if (!send_string_without_coro(
415+
fd, lwan_http_status_as_string_with_code(status), MSG_MORE))
416+
goto shutdown_and_close;
417+
418+
if (!send_string_without_coro(fd, "\r\nConnection: close", MSG_MORE))
419+
goto shutdown_and_close;
420+
421+
if (!send_string_without_coro(fd, "\r\nContent-Type: text/html", MSG_MORE))
422+
goto shutdown_and_close;
423+
424+
if (send_buffer_without_coro(fd, l->headers.value, l->headers.len,
425+
MSG_MORE)) {
426+
struct lwan_strbuf buffer;
427+
428+
lwan_strbuf_init(&buffer);
429+
lwan_fill_default_response(&buffer, status);
430+
431+
send_buffer_without_coro(fd, lwan_strbuf_get_buffer(&buffer),
432+
lwan_strbuf_get_length(&buffer), 0);
433+
434+
lwan_strbuf_free(&buffer);
435+
}
436+
437+
shutdown_and_close:
438+
shutdown(fd, SHUT_RDWR);
439+
close(fd);
440+
}
441+
363442
__attribute__((noreturn)) static int process_request_coro(struct coro *coro,
364443
void *data)
365444
{
@@ -397,12 +476,28 @@ __attribute__((noreturn)) static int process_request_coro(struct coro *coro,
397476
.value = coro_malloc(conn->coro, request_buffer_size),
398477
.len = request_buffer_size,
399478
};
479+
480+
if (UNLIKELY(!buffer.value)) {
481+
/* If CONN_TLS is set at this point, we can send responses just
482+
* fine and they'll be encrypted by the kernel. However,
483+
* send_last_response_without_coro() can't send the response if
484+
* this bit is set as it has been designed to be used in cases
485+
* where coroutines were not created yet. */
486+
conn->flags &= ~CONN_TLS;
487+
488+
send_last_response_without_coro(lwan, conn, HTTP_UNAVAILABLE);
489+
490+
coro_yield(conn->coro, CONN_CORO_ABORT);
491+
__builtin_unreachable();
492+
}
493+
400494
init_gen = 2;
401495
} else {
402496
buffer = (struct lwan_value){
403497
.value = alloca(request_buffer_size),
404498
.len = request_buffer_size,
405499
};
500+
406501
init_gen = 1;
407502
}
408503

@@ -638,85 +733,6 @@ static void update_date_cache(struct lwan_thread *thread)
638733
thread->date.expires);
639734
}
640735

641-
__attribute__((cold))
642-
static bool send_buffer_without_coro(int fd, const char *buf, size_t buf_len, int flags)
643-
{
644-
size_t total_sent = 0;
645-
646-
for (int try = 0; try < 10; try++) {
647-
size_t to_send = buf_len - total_sent;
648-
if (!to_send)
649-
return true;
650-
651-
ssize_t sent = send(fd, buf + total_sent, to_send, flags);
652-
if (sent <= 0) {
653-
if (errno == EINTR)
654-
continue;
655-
if (errno == EAGAIN)
656-
continue;
657-
break;
658-
}
659-
660-
total_sent += (size_t)sent;
661-
}
662-
663-
return false;
664-
}
665-
666-
__attribute__((cold))
667-
static bool send_string_without_coro(int fd, const char *str, int flags)
668-
{
669-
return send_buffer_without_coro(fd, str, strlen(str), flags);
670-
}
671-
672-
__attribute__((cold)) static void
673-
send_last_response_without_coro(const struct lwan *l,
674-
const struct lwan_connection *conn,
675-
enum lwan_http_status status)
676-
{
677-
int fd = lwan_connection_get_fd(l, conn);
678-
679-
if (conn->flags & CONN_TLS) {
680-
/* There's nothing that can be done here if a client is expecting a
681-
* TLS connection: the TLS handshake requires a coroutine as it
682-
* might yield. (In addition, the TLS handshake might allocate
683-
* memory, and if you couldn't create a coroutine at this point,
684-
* it's unlikely you'd be able to allocate memory for the TLS
685-
* context anyway.) */
686-
goto shutdown_and_close;
687-
}
688-
689-
if (!send_string_without_coro(fd, "HTTP/1.0 ", MSG_MORE))
690-
goto shutdown_and_close;
691-
692-
if (!send_string_without_coro(
693-
fd, lwan_http_status_as_string_with_code(status), MSG_MORE))
694-
goto shutdown_and_close;
695-
696-
if (!send_string_without_coro(fd, "\r\nConnection: close", MSG_MORE))
697-
goto shutdown_and_close;
698-
699-
if (!send_string_without_coro(fd, "\r\nContent-Type: text/html", MSG_MORE))
700-
goto shutdown_and_close;
701-
702-
if (send_buffer_without_coro(fd, l->headers.value, l->headers.len,
703-
MSG_MORE)) {
704-
struct lwan_strbuf buffer;
705-
706-
lwan_strbuf_init(&buffer);
707-
lwan_fill_default_response(&buffer, status);
708-
709-
send_buffer_without_coro(fd, lwan_strbuf_get_buffer(&buffer),
710-
lwan_strbuf_get_length(&buffer), 0);
711-
712-
lwan_strbuf_free(&buffer);
713-
}
714-
715-
shutdown_and_close:
716-
shutdown(fd, SHUT_RDWR);
717-
close(fd);
718-
}
719-
720736
static ALWAYS_INLINE bool spawn_coro(struct lwan_connection *conn,
721737
struct coro_switcher *switcher,
722738
struct timeout_queue *tq)

0 commit comments

Comments
 (0)