Index: aprlib.def =================================================================== RCS file: /home/cvspublic/apr/aprlib.def,v retrieving revision 1.55 diff -u -r1.55 aprlib.def --- aprlib.def 2000/12/18 21:52:05 1.55 +++ aprlib.def 2000/12/19 09:53:53 @@ -275,3 +275,7 @@ ; apr_optreset ; apr_optarg +; More apr_thread_proc.h APIs + apr_setprocattr_childin + apr_setprocattr_childout + apr_setprocattr_childerr Index: threadproc/win32/proc.c =================================================================== RCS file: /home/cvspublic/apr/threadproc/win32/proc.c,v retrieving revision 1.40 diff -u -r1.40 proc.c --- threadproc/win32/proc.c 2000/12/15 15:02:40 1.40 +++ threadproc/win32/proc.c 2000/12/19 09:53:54 @@ -65,6 +65,12 @@ #include #include +/* + * some of the ideas expressed herein are based off of Microsoft Knowledge Base article: + * Q190351 + * + */ + apr_status_t apr_createprocattr_init(apr_procattr_t **new, apr_pool_t *cont) { (*new) = (apr_procattr_t *)apr_palloc(cont, sizeof(apr_procattr_t)); @@ -88,13 +94,13 @@ return APR_SUCCESS; } -apr_status_t apr_setprocattr_io(apr_procattr_t *attr, apr_int32_t in, - apr_int32_t out, apr_int32_t err) +static apr_status_t open_nt_process_pipe(apr_file_t **read, apr_file_t **write, + apr_int32_t iBlockingMode, apr_pool_t *cntxt) { apr_status_t stat; BOOLEAN bAsyncRead, bAsyncWrite; - if (in) { - switch (in) { + + switch (iBlockingMode) { case APR_FULL_BLOCK: bAsyncRead = bAsyncWrite = FALSE; break; @@ -109,94 +115,231 @@ default: bAsyncRead = TRUE; bAsyncWrite = TRUE; - } - if ((stat = apr_create_nt_pipe(&attr->child_in, &attr->parent_in, - bAsyncRead, bAsyncWrite, - attr->cntxt)) != APR_SUCCESS) { + } + if ((stat = apr_create_nt_pipe(read, write, bAsyncRead, bAsyncWrite, + cntxt)) != APR_SUCCESS) + return stat; + return APR_SUCCESS; +} + + +apr_status_t apr_setprocattr_io(apr_procattr_t *attr, apr_int32_t in, + apr_int32_t out, apr_int32_t err) +{ + apr_status_t stat; + HANDLE hCurrentProcess = GetCurrentProcess(); + HANDLE h = NULL; + + if (in) { + stat = open_nt_process_pipe(&attr->child_in, &attr->parent_in, in, attr->cntxt); + if (stat != APR_SUCCESS) return stat; - } + /* Create new non-inheritable versions of handles that + * the child process doesn't care about. Otherwise, the child + * inherits these handles; resulting in non-closeable handles + * to the respective pipes. + */ + h = attr->parent_in->filehand; + if (!DuplicateHandle(hCurrentProcess, attr->parent_in->filehand, hCurrentProcess, + &attr->parent_in->filehand, 0, FALSE, DUPLICATE_SAME_ACCESS)) + return apr_get_os_error(); + /* + * Close the inerhitable handle we don't need anymore. + */ + CloseHandle(h); } if (out) { - switch (out) { - case APR_FULL_BLOCK: - bAsyncRead = bAsyncWrite = FALSE; - break; - case APR_PARENT_BLOCK: - bAsyncRead = FALSE; - bAsyncWrite = TRUE; - break; - case APR_CHILD_BLOCK: - bAsyncRead = TRUE; - bAsyncWrite = FALSE; - break; - default: - bAsyncRead = TRUE; - bAsyncWrite = TRUE; - } - if ((stat = apr_create_nt_pipe(&attr->parent_out, &attr->child_out, - bAsyncRead, bAsyncWrite, - attr->cntxt)) != APR_SUCCESS) { + stat = open_nt_process_pipe(&attr->parent_out, &attr->child_out, + out, attr->cntxt); + if (stat != APR_SUCCESS) return stat; - } + /* Create new non-inheritable versions of handles that + * the child process doesn't care about. Otherwise, the child + * inherits these handles; resulting in non-closeable handles + * to the respective pipes. + */ + h = attr->parent_out->filehand; + if (!DuplicateHandle(hCurrentProcess, attr->parent_out->filehand, hCurrentProcess, + &attr->parent_out->filehand, 0, FALSE, DUPLICATE_SAME_ACCESS)) + return apr_get_os_error(); + /* + * Close the inerhitable handle we don't need anymore. + */ + CloseHandle(h); } if (err) { - switch (err) { - case APR_FULL_BLOCK: - bAsyncRead = bAsyncWrite = FALSE; - break; - case APR_PARENT_BLOCK: - bAsyncRead = FALSE; - bAsyncWrite = TRUE; - break; - case APR_CHILD_BLOCK: - bAsyncRead = TRUE; - bAsyncWrite = FALSE; - break; - default: - bAsyncRead = TRUE; - bAsyncWrite = TRUE; - } - if ((stat = apr_create_nt_pipe(&attr->parent_err, &attr->child_err, - bAsyncRead, bAsyncWrite, - attr->cntxt)) != APR_SUCCESS) { + stat = open_nt_process_pipe(&attr->parent_err, &attr->child_err, + err, attr->cntxt); + if (stat != APR_SUCCESS) return stat; - } + /* Create new non-inheritable versions of handles that + * the child process doesn't care about. Otherwise, the child + * inherits these handles; resulting in non-closeable handles + * to the respective pipes. + */ + h = attr->parent_err->filehand; + if (!DuplicateHandle(hCurrentProcess, attr->parent_err->filehand, hCurrentProcess, + &attr->parent_err->filehand, 0, FALSE, DUPLICATE_SAME_ACCESS)) + return apr_get_os_error(); + /* + * Close the inerhitable handle we don't need anymore. + */ + CloseHandle(h); } return APR_SUCCESS; } -#if 0 + apr_status_t apr_setprocattr_childin(apr_procattr_t *attr, apr_file_t *child_in, apr_file_t *parent_in) { + apr_status_t stat; + HANDLE h; + HANDLE hCurrentProcess = GetCurrentProcess(); + + if (attr->child_in == NULL && attr->parent_in == NULL) { + stat = open_nt_process_pipe(&attr->child_in, &attr->parent_in, APR_FULL_BLOCK, attr->cntxt); + if (stat != APR_SUCCESS) + return stat; + /* Create new non-inheritable versions of handles that + * the child process doesn't care about. Otherwise, the child + * inherits these handles; resulting in non-closeable handles + * to the respective pipes. + */ + h = attr->parent_in->filehand; + if (!DuplicateHandle(hCurrentProcess, attr->parent_in->filehand, hCurrentProcess, + &attr->parent_in->filehand, 0, FALSE, DUPLICATE_SAME_ACCESS)) + return apr_get_os_error(); + /* Close the inerhitable handle we don't need anymore. */ + CloseHandle(h); + } + + if (child_in != NULL) { + /* Can't use apr_dupfile here because it creates a non-inhertible handle, + * and apr_open_file'd apr_file_t's are non-inheritable, so we must + * assume we need to make an inheritable handle. + */ + if (!CloseHandle(attr->child_in->filehand)) + return apr_get_os_error(); + if (!DuplicateHandle(hCurrentProcess, child_in->filehand, hCurrentProcess, + &attr->child_in->filehand, 0, TRUE, DUPLICATE_SAME_ACCESS)) + return apr_get_os_error(); + } + + if (parent_in != NULL) { + /* Can't use apr_dupfile here because it creates a non-inhertible handle, + * and apr_open_file'd apr_file_t's are non-inheritable, so we must + * assume we need to make an inheritable handle. + */ + if (!CloseHandle(attr->parent_in)) + return apr_get_os_error(); + if (!DuplicateHandle(hCurrentProcess, parent_in->filehand, hCurrentProcess, + &attr->parent_in->filehand, 0, TRUE, DUPLICATE_SAME_ACCESS)) + return apr_get_os_error(); + } + + return APR_SUCCESS; } apr_status_t apr_setprocattr_childout(apr_procattr_t *attr, apr_file_t *child_out, apr_file_t *parent_out) { - if (attr->child_out == NULL && attr->parent_out == NULL) - apr_create_pipe(&attr->child_out, &attr->parent_out, attr->cntxt); + apr_status_t stat; + HANDLE hCurrentProcess = GetCurrentProcess(); + HANDLE h = NULL; - if (child_out != NULL) - apr_dupfile(&attr->child_out, child_out, attr->cntxt); + if (attr->child_out == NULL && attr->parent_out == NULL) { + stat = open_nt_process_pipe(&attr->child_out, &attr->parent_out, APR_FULL_BLOCK, attr->cntxt); + if (stat != APR_SUCCESS) + return stat; + /* Create new non-inheritable versions of handles that + * the child process doesn't care about. Otherwise, the child + * inherits these handles; resulting in non-closeable handles + * to the respective pipes. + */ + h = attr->parent_out->filehand; + if (!DuplicateHandle(hCurrentProcess, attr->parent_out->filehand, hCurrentProcess, + &attr->parent_out->filehand, 0, FALSE, DUPLICATE_SAME_ACCESS)) + return apr_get_os_error(); + /* Close the inerhitable handle we don't need anymore. */ + CloseHandle(h); + } + + if (child_out != NULL) { + /* Can't use apr_dupfile here because it creates a non-inhertible handle, + * and apr_open_file'd apr_file_t's are non-inheritable, so we must + * assume we need to make an inheritable handle. + */ + if (!CloseHandle(attr->child_out->filehand)) + return apr_get_os_error(); + if (!DuplicateHandle(hCurrentProcess, child_out->filehand, hCurrentProcess, + &attr->child_out->filehand, 0, TRUE, DUPLICATE_SAME_ACCESS)) + return apr_get_os_error(); + } - if (parent_out != NULL) - apr_dupfile(&attr->parent_out, parent_out, attr->cntxt); + if (parent_out != NULL) { + /* Can't use apr_dupfile here because it creates a non-inhertible handle, + * and apr_open_file'd apr_file_t's are non-inheritable, so we must + * assume we need to make an inheritable handle. + */ + if (!CloseHandle(attr->parent_out)) + return apr_get_os_error(); + if (!DuplicateHandle(hCurrentProcess, parent_out->filehand, hCurrentProcess, + &attr->parent_out->filehand, 0, TRUE, DUPLICATE_SAME_ACCESS)) + return apr_get_os_error(); + } return APR_SUCCESS; } + apr_status_t apr_setprocattr_childerr(apr_procattr_t *attr, apr_file_t *child_err, apr_file_t *parent_err) { - if (attr->child_err == NULL && attr->parent_err == NULL) - apr_create_pipe(&attr->child_err, &attr->parent_err, attr->cntxt); + apr_status_t stat; + HANDLE h = NULL; + HANDLE hCurrentProcess = GetCurrentProcess(); - if (child_err != NULL) - apr_dupfile(&attr->child_err, child_err, attr->cntxt); + if (attr->child_err == NULL && attr->parent_err == NULL) { + stat = open_nt_process_pipe(&attr->child_err, &attr->parent_err, APR_FULL_BLOCK, attr->cntxt); + if (stat != APR_SUCCESS) + return stat; + /* Create new non-inheritable versions of handles that + * the child process doesn't care about. Otherwise, the child + * inherits these handles; resulting in non-closeable handles + * to the respective pipes. + */ + h = attr->parent_err->filehand; + if (!DuplicateHandle(hCurrentProcess, attr->parent_err->filehand, hCurrentProcess, + &attr->parent_err->filehand, 0, FALSE, DUPLICATE_SAME_ACCESS)) + return apr_get_os_error(); + /* Close the inerhitable handle we don't need anymore. */ + CloseHandle(h); + } + + if (child_err != NULL) { + /* Can't use apr_dupfile here because it creates a non-inhertible handle, + * and apr_open_file'd apr_file_t's are non-inheritable, so we must + * assume we need to make an inheritable handle. + */ + if (!CloseHandle(attr->child_err)) + return apr_get_os_error(); + if (!DuplicateHandle(hCurrentProcess, child_err->filehand, hCurrentProcess, + &attr->child_err->filehand, 0, TRUE, DUPLICATE_SAME_ACCESS)) + return apr_get_os_error(); + } - if (parent_err != NULL) - apr_dupfile(&attr->parent_err, parent_err, attr->cntxt); + if (parent_err != NULL) { + /* Can't use apr_dupfile here because it creates a non-inhertible handle, + * and apr_open_file'd apr_file_t's are non-inheritable, so we must + * assume we need to make an inheritable handle. + */ + if (!CloseHandle(attr->parent_err)) + return apr_get_os_error(); + if (!DuplicateHandle(hCurrentProcess, parent_err->filehand, hCurrentProcess, + &attr->parent_err->filehand, 0, TRUE, DUPLICATE_SAME_ACCESS)) + return apr_get_os_error(); + } return APR_SUCCESS; } -#endif + apr_status_t apr_setprocattr_dir(apr_procattr_t *attr, const char *dir) { @@ -241,12 +384,9 @@ { int i, iEnvBlockLen; char *cmdline; - HANDLE hCurrentProcess; - HANDLE hParentindup, hParentoutdup,hParenterrdup; char ppid[20]; char *envstr; char *pEnvBlock, *pNext; - apr_status_t rv; PROCESS_INFORMATION pi; new->in = attr->parent_in; @@ -310,58 +450,6 @@ while (args && args[i]) { cmdline = apr_pstrcat(cont, cmdline, " ", args[i], NULL); i++; - } - /* - * When the pipe handles are created, the security descriptor - * indicates that the handle can be inherited. However, we do not - * want the server side handles to the pipe to be inherited by the - * child CGI process. If the child CGI does inherit the server - * side handles, then the child may be left around if the server - * closes its handles (e.g. if the http connection is aborted), - * because the child will have a valid copy of handles to both - * sides of the pipes, and no I/O error will occur. Microsoft - * recommends using DuplicateHandle to turn off the inherit bit - * under NT and Win95. - */ - hCurrentProcess = GetCurrentProcess(); - if ((attr->child_in && !DuplicateHandle(hCurrentProcess, attr->parent_in->filehand, - hCurrentProcess, - &hParentindup, 0, FALSE, - DUPLICATE_SAME_ACCESS)) - || (attr->child_out && !DuplicateHandle(hCurrentProcess, attr->parent_out->filehand, - hCurrentProcess, &hParentoutdup, - 0, FALSE, DUPLICATE_SAME_ACCESS)) - || (attr->child_err && !DuplicateHandle(hCurrentProcess, attr->parent_err->filehand, - hCurrentProcess, &hParenterrdup, - 0, FALSE, DUPLICATE_SAME_ACCESS))) { - rv = apr_get_os_error(); - if (attr->child_in) { - apr_close(attr->child_in); - apr_close(attr->parent_in); - } - if (attr->child_out) { - apr_close(attr->child_out); - apr_close(attr->parent_out); - } - if (attr->child_err) { - apr_close(attr->child_err); - apr_close(attr->parent_err); - } - return rv; - } - else { - if (attr->child_in) { - CloseHandle(attr->parent_in->filehand); - attr->parent_in->filehand = hParentindup; - } - if (attr->child_out) { - CloseHandle(attr->parent_out->filehand); - attr->parent_out->filehand = hParentoutdup; - } - if (attr->child_err) { - CloseHandle(attr->parent_err->filehand); - attr->parent_err->filehand = hParenterrdup; - } } _itoa(_getpid(), ppid, 10);