--- a/src/server/safs/proxy.c Wed Feb 25 23:14:47 2026 +0100 +++ b/src/server/safs/proxy.c Thu Feb 26 21:35:53 2026 +0100 @@ -130,6 +130,17 @@ ret = REQ_ABORTED; } + if(client->last_event != &proxy->event && proxy->event.fn != NULL) { + if(!ev_remove_poll(client->ev, proxy->event.object)) { + proxy_unref(proxy); + } else { + log_ereport(LOG_FAILURE, "proxy_response_finished: cannot remove poll"); + } + proxy->event.finish = NULL; + } + + // return to nsapi threadpool + net_setnonblock(proxy->sn->csd, 0); nsapi_function_return(proxy->sn, proxy->rq, ret); proxy_unref(proxy); @@ -137,7 +148,7 @@ static int proxy_request_read_event(EventHandler *eh, Event *event) { ProxyRequest *proxy = event->cookie; - if(http_client_process(proxy->client)) { + if(http_client_process(proxy->client, event)) { if(proxy->client->error == 0) { return 1; } @@ -161,7 +172,7 @@ if(st->io_errno == EWOULDBLOCK) { ret = HTTP_CLIENT_CALLBACK_WOULD_BLOCK; // is there already an poll event for csd? - if(!proxy->event.cookie) { + if(!proxy->event.fn) { proxy->ref++; proxy->event.cookie = proxy; proxy->event.fn = proxy_request_read_event; @@ -181,16 +192,41 @@ static ssize_t proxy_response_write(HttpClient *client, void *buf, size_t nbytes, void *userdata) { ProxyRequest *proxy = userdata; ssize_t ret = net_write(proxy->sn->csd, buf, nbytes); - // TODO: handle errors + if(ret == NETBUF_EOF) { + ret = HTTP_CLIENT_CALLBACK_ERROR; + } else if(ret < 0) { + IOStream *st = proxy->sn->csd; + if(st->io_errno == EWOULDBLOCK) { + // Is there already an poll event for csd? + if(client->last_event == &proxy->event) { + // Yes, there is already an event, and it even is the event that triggert this call. + // Make sure it is a write event + proxy->event.events = EVENT_POLLOUT; + return HTTP_CLIENT_CALLBACK_WOULD_BLOCK; + } else if(proxy->event.fn != NULL) { + // There is an inactive event, probably a read event + // Remove the old event before we add a write event + if(ev_remove_poll(client->ev, proxy->event.object)) { + log_ereport(LOG_FAILURE, "proxy_response_write: cannot remove poll"); + return HTTP_CLIENT_CALLBACK_ERROR; + } + } else { + proxy->ref++; + proxy->event.cookie = proxy; + proxy->event.fn = proxy_request_read_event; + proxy->event.finish = proxy_request_read_finished; + } + // Add write event + if(event_pollout(client->ev, proxy->sn->csd, &proxy->event)) { + proxy_unref(proxy); + log_ereport(LOG_FAILURE, "proxy_response_write: cannot add write poll"); + } + return HTTP_CLIENT_CALLBACK_ERROR; + } + } return ret; } -static void proxy_request_finished(HttpClient *client, void *userdata) { - ProxyRequest *proxy = userdata; - net_setnonblock(proxy->sn->csd, 0); - nsapi_saf_return(proxy->sn, proxy->rq, REQ_PROCEED); -} - int http_reverse_proxy_service(pblock *param, Session *sn, Request *rq) { EventHandler *ev = sn->ev; const char *method = pblock_findkeyval(pb_key_method, rq->reqpb); @@ -396,7 +432,7 @@ client->response_start_userdata = proxy; client->response_body_write = proxy_response_write; client->response_body_write_userdata = proxy; - client->response_finished = proxy_request_finished; + client->response_finished = proxy_response_finished; client->response_finished_userdata = proxy; net_setnonblock(sn->csd, 1);