1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

cgi: add spawn reap callback

This commit is contained in:
Andy Green 2020-07-17 15:35:28 +01:00
parent 6ae43ee06e
commit da7ef0468b
7 changed files with 89 additions and 11 deletions

View file

@ -683,6 +683,7 @@ __lws_close_free_wsi_final(struct lws *wsi)
#ifdef LWS_WITH_CGI
if (wsi->http.cgi) {
lws_spawn_piped_destroy(&wsi->http.cgi->lsp);
lws_sul_cancel(&wsi->http.cgi->sul_grace);
lws_free_set_NULL(wsi->http.cgi);
}
#endif

View file

@ -337,12 +337,16 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
else
wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__CGI;
if (wsi->http.cgi && wsi->http.cgi->cgi_transaction_over)
if (wsi->http.cgi && wsi->http.cgi->cgi_transaction_over) {
lwsl_notice("%s: txn over\n", __func__);
return -1;
}
break;
}
if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_CHUNK_END) {
if ((wsi->http.cgi && wsi->http.cgi->cgi_transaction_over) ||
(wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_CHUNK_END)) {
if (!wsi->mux_substream) {
memcpy(buf + LWS_PRE, "0\x0d\x0a\x0d\x0a", 5);
lwsl_debug("writing chunk term and exiting\n");
@ -791,6 +795,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
if (wsi->http.cgi->post_in_expected && args->stdwsi[LWS_STDIN] &&
args->stdwsi[LWS_STDIN]->desc.filefd > 0) {
wsi->http.cgi->post_in_expected -= n;
if (!wsi->http.cgi->post_in_expected) {
struct lws *siwsi = args->stdwsi[LWS_STDIN];
@ -803,8 +808,9 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
*/
lwsl_notice("%s: expected POST in end: "
"closing stdin wsi %p, fd %d\n",
__func__, siwsi, siwsi->desc.sockfd);
"closing stdin wsi %p, fd %d\n",
__func__, siwsi,
siwsi->desc.sockfd);
/*
* We don't want the child / parent relationship
@ -815,6 +821,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
lws_remove_child_from_any_parent(siwsi);
lws_wsi_close(siwsi, LWS_TO_KILL_ASYNC);
wsi->http.cgi->lsp->stdwsi[LWS_STDIN] = NULL;
lws_spawn_stdwsi_closed(wsi->http.cgi->lsp, siwsi);
}
}

View file

@ -68,6 +68,43 @@ urlencode(const char *in, int inlen, char *out, int outlen)
return out - start;
}
static void
lws_cgi_grace(lws_sorted_usec_list_t *sul)
{
struct lws_cgi *cgi = lws_container_of(sul, struct lws_cgi, sul_grace);
/* act on the reap cb from earlier */
lwsl_notice("%s: wsi %p\n", __func__, cgi->wsi);
if (!cgi->wsi->http.cgi->post_in_expected)
cgi->wsi->http.cgi->cgi_transaction_over = 1;
lws_callback_on_writable(cgi->wsi);
}
static void
lws_cgi_reap_cb(void *opaque, lws_usec_t *accounting, siginfo_t *si,
int we_killed_him)
{
struct lws *wsi = (struct lws *)opaque;
/*
* The cgi has come to an end, by itself or with a signal...
*/
lwsl_notice("%s: wsi %p post_in_expected %d\n", __func__, wsi,
(int)wsi->http.cgi->post_in_expected);
/*
* Grace period to handle the incoming stdout
*/
lws_sul_schedule(wsi->context, wsi->tsi, &wsi->http.cgi->sul_grace,
lws_cgi_grace, 1 * LWS_US_PER_SEC);
}
int
lws_cgi(struct lws *wsi, const char * const *exec_array,
int script_uri_path_len, int timeout_secs,
@ -357,6 +394,8 @@ lws_cgi(struct lws *wsi, const char * const *exec_array,
info.vh = wsi->vhost;
info.ops = &role_ops_cgi;
info.plsp = &wsi->http.cgi->lsp;
info.opaque = wsi;
info.reap_cb = lws_cgi_reap_cb;
/*
* Actually having made the env, as a cgi we don't need the ah
@ -386,6 +425,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array,
return 0;
bail:
lws_sul_cancel(&wsi->http.cgi->sul_grace);
lws_free_set_NULL(wsi->http.cgi);
lwsl_err("%s: failed\n", __func__);
@ -561,7 +601,7 @@ post_hpack_recode:
cmd = LWS_WRITE_HTTP_HEADERS_CONTINUATION;
if (wsi->http.cgi->headers_dumped + n !=
wsi->http.cgi->headers_pos) {
wsi->http.cgi->headers_pos) {
lwsl_notice("adding no fin flag\n");
cmd |= LWS_WRITE_NO_FIN;
}
@ -578,14 +618,21 @@ post_hpack_recode:
wsi->http.cgi->headers_pos) {
wsi->hdr_state = LHCS_PAYLOAD;
lws_free_set_NULL(wsi->http.cgi->headers_buf);
lwsl_debug("freed cgi headers\n");
lwsl_debug("%s: freed cgi headers\n", __func__);
if (wsi->http.cgi->post_in_expected) {
lwsl_notice("%s: post data still expected, asking for writeable\n", __func__);
lws_callback_on_writable(wsi);
}
} else {
wsi->reason_bf |=
LWS_CB_REASON_AUX_BF__CGI_HEADERS;
lws_callback_on_writable(wsi);
}
/* writeability becomes uncertain now we wrote
/*
* writeability becomes uncertain now we wrote
* something, we must return to the event loop
*/
return 0;
@ -962,7 +1009,7 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt)
cgi = *pcgi;
pcgi = &(*pcgi)->cgi_list;
if (cgi->lsp->child_pid <= 0)
if (!cgi || !cgi->lsp || cgi->lsp->child_pid <= 0)
continue;
/* we deferred killing him after reaping his PID */
@ -1040,7 +1087,7 @@ lws_cgi_remove_and_kill(struct lws *wsi)
pcgi = &(*pcgi)->cgi_list;
}
if (wsi->http.cgi->headers_buf) {
lwsl_debug("close: freed cgi headers\n");
lwsl_debug("%s: close: freed cgi headers\n", __func__);
lws_free_set_NULL(wsi->http.cgi->headers_buf);
}
/* we have a cgi going, we must kill it */

View file

@ -46,6 +46,27 @@ rops_handle_POLLIN_cgi(struct lws_context_per_thread *pt, struct lws *wsi,
return LWS_HPI_RET_WSI_ALREADY_DIED;
}
if (!wsi->parent) {
lwsl_notice("%s: stdwsi content with parent\n",
__func__);
return LWS_HPI_RET_HANDLED;
}
if (!wsi->parent->http.cgi) {
lwsl_notice("%s: stdwsi content with deleted cgi object\n",
__func__);
return LWS_HPI_RET_HANDLED;
}
if (!wsi->parent->http.cgi->lsp) {
lwsl_notice("%s: stdwsi content with reaped lsp\n",
__func__);
return LWS_HPI_RET_HANDLED;
}
args.ch = wsi->lsp_channel;
args.stdwsi = &wsi->parent->http.cgi->lsp->stdwsi[0];
args.hdr_state = wsi->hdr_state;

View file

@ -55,7 +55,8 @@ struct lws;
struct lws_cgi {
struct lws_cgi *cgi_list;
struct lws_spawn_piped *lsp;
struct lws_spawn_piped *lsp;
lws_sorted_usec_list_t sul_grace;
struct lws *wsi; /* owner */
unsigned char *headers_buf;

View file

@ -2345,6 +2345,7 @@ lws_http_transaction_completed(struct lws *wsi)
wsi->http.cgi_transaction_complete = 1;
lws_cgi_remove_and_kill(wsi);
lws_spawn_piped_destroy(&wsi->http.cgi->lsp);
lws_sul_cancel(&wsi->http.cgi->sul_grace);
lws_free_set_NULL(wsi->http.cgi);
wsi->http.cgi_transaction_complete = 0;

View file

@ -31,6 +31,6 @@ fi
echo "<br/>done"
echo "</body></html>"
sleep 0.5
exit 0