[Remove entries to the current 2.0 section below, when backported]
+ *) mod_cgi, mod_cgid, mod_ext_filter: Log errors when scripts cannot
+ be started on Unix because of such problems as bad permissions,
+ bad shebang line, etc. [Jeff Trawick]
+
*) Fix suexec compile error under SUNOS4, where strerror() doesn't
exist. PR 5913, 9977.
[Jonathan W Miner <Jonathan.W.Miner@lmco.com>]
static apr_status_t ef_output_filter(ap_filter_t *, apr_bucket_brigade *);
#define DBGLVL_SHOWOPTIONS 1
+#define DBGLVL_ERRORCHECK 2
#define DBGLVL_GORY 9
+#define ERRFN_USERDATA_KEY "EXTFILTCHILDERRFN"
+
static void *create_ef_dir_conf(apr_pool_t *p, char *dummy)
{
ef_dir_t *dc = (ef_dir_t *)apr_pcalloc(p, sizeof(ef_dir_t));
return apr_file_close(vfile);
}
+static void child_errfn(apr_pool_t *p, apr_status_t err, const char *desc)
+{
+ request_rec *r;
+ void *vr;
+
+ apr_pool_userdata_get(&vr, ERRFN_USERDATA_KEY, p);
+ r = vr;
+
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, "%s", desc);
+}
+
/* init_ext_filter_process: get the external filter process going
* This is per-filter-instance (i.e., per-request) initialization.
*/
ap_assert(rc == APR_SUCCESS);
}
+ rc = apr_procattr_child_errfn_set(ctx->procattr, child_errfn);
+ ap_assert(rc == APR_SUCCESS);
+ apr_pool_userdata_set(f->r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ctx->p);
+
+ if (dc->debug >= DBGLVL_ERRORCHECK) {
+ rc = apr_procattr_error_check_set(ctx->procattr, 1);
+ ap_assert(rc == APR_SUCCESS);
+ }
+
/* add standard CGI variables as well as DOCUMENT_URI, DOCUMENT_PATH_INFO,
* and QUERY_STRING_UNESCAPED
*/
#define DEFAULT_LOGBYTES 10385760
#define DEFAULT_BUFBYTES 1024
+#define ERRFN_USERDATA_KEY "CGICHILDERRFN"
+
typedef struct {
const char *logname;
long logbytes;
}
}
+static void cgi_child_errfn(apr_pool_t *pool, apr_status_t err,
+ const char *description)
+{
+ request_rec *r;
+ void *vr;
+
+ apr_pool_userdata_get(&vr, ERRFN_USERDATA_KEY, pool);
+ r = vr;
+
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, "%s", description);
+}
+
static apr_status_t run_cgi_child(apr_file_t **script_out,
apr_file_t **script_in,
apr_file_t **script_err,
e_info->cmd_type)) != APR_SUCCESS) ||
((rc = apr_procattr_detach_set(procattr,
- e_info->detached)) != APR_SUCCESS)) {
+ e_info->detached)) != APR_SUCCESS) ||
+ ((rc = apr_procattr_child_errfn_set(procattr, cgi_child_errfn)) != APR_SUCCESS)) {
/* Something bad happened, tell the world. */
ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
"couldn't set child process attributes: %s", r->filename);
}
else {
+ apr_pool_userdata_set(r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, p);
+
procnew = apr_pcalloc(p, sizeof(*procnew));
if (e_info->prog_type == RUN_AS_SSI) {
SPLIT_AND_PASS_PRETAG_BUCKETS(*(e_info->bb), e_info->ctx,
#define SSI_REQ 2
#define GETPID_REQ 3 /* get the pid of script created for prior request */
+#define ERRFN_USERDATA_KEY "CGIDCHILDERRFN"
+
/* DEFAULT_CGID_LISTENBACKLOG controls the max depth on the unix socket's
* pending connection queue. If a bunch of cgi requests arrive at about
* the same time, connections from httpd threads/processes will back up
apr_size_t uri_len;
apr_size_t args_len;
apr_size_t mod_userdir_user_len;
+ int loglevel; /* to stuff in server_rec */
} cgid_req_t;
/* This routine is called to create the argument list to be passed
if (stat != APR_SUCCESS) {
return stat;
}
+ r->server->loglevel = req->loglevel;
if (req->req_type == GETPID_REQ) {
/* no more data sent for this request */
return APR_SUCCESS;
if (user != NULL) {
req.mod_userdir_user_len = strlen(user);
}
+ req.loglevel = r->server->loglevel;
/* Write the request header */
if ((stat = sock_write(fd, &req, sizeof(req))) != APR_SUCCESS) {
}
}
+static void cgid_child_errfn(apr_pool_t *pool, apr_status_t err,
+ const char *description)
+{
+ request_rec *r;
+ void *vr;
+
+ apr_pool_userdata_get(&vr, ERRFN_USERDATA_KEY, pool);
+ r = vr;
+
+ /* sure we got r, but don't call ap_log_rerror() because we don't
+ * have r->headers_in and possibly other storage referenced by
+ * ap_log_rerror()
+ */
+ ap_log_error(APLOG_MARK, APLOG_ERR, err, r->server, "%s", description);
+}
+
static int cgid_server(void *data)
{
struct sockaddr_un unix_addr;
((rc = apr_procattr_child_out_set(procattr, inout, NULL)) != APR_SUCCESS) ||
((rc = apr_procattr_dir_set(procattr,
ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS) ||
- ((rc = apr_procattr_cmdtype_set(procattr, cmd_type)) != APR_SUCCESS)) {
+ ((rc = apr_procattr_cmdtype_set(procattr, cmd_type)) != APR_SUCCESS) ||
+ ((rc = apr_procattr_child_errfn_set(procattr, cgid_child_errfn)) != APR_SUCCESS)) {
/* Something bad happened, tell the world. */
ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
"couldn't set child process attributes: %s", r->filename);
}
else {
+ apr_pool_userdata_set(r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ptrans);
+
argv = (const char * const *)create_argv(r->pool, NULL, NULL, NULL, argv0, r->args);
/* We want to close sd2 for the new CGI process too.