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:
parent
6ae43ee06e
commit
da7ef0468b
7 changed files with 89 additions and 11 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -31,6 +31,6 @@ fi
|
|||
|
||||
echo "<br/>done"
|
||||
echo "</body></html>"
|
||||
|
||||
sleep 0.5
|
||||
exit 0
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue