(if the app wants to burn the cycles, that is)
With a new attribute set, apr_proc_create() will check for some common problems prior to forking. This enables the caller to handle errors more gracefully with no funky code.
I have half a mind to make this attribute set by default with APR 1.0 and let apps that run apr_proc_create() constantly and don't want the extra overhead (e.g., mod_cgi) turn it off if they want.
Comments?
Better name for the attribute than apr_procattr_error_check_set() pretty please?
Index: include/apr_thread_proc.h
===================================================================
RCS file: /home/cvs/apr/include/apr_thread_proc.h,v
retrieving revision 1.91
diff -u -r1.91 apr_thread_proc.h
--- include/apr_thread_proc.h 6 Feb 2003 18:50:30 -0000 1.91
+++ include/apr_thread_proc.h 7 Feb 2003 12:56:56 -0000
@@ -512,6 +512,20 @@
APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr,
apr_child_errfn_t
*errfn);
+/**
+ * Specify that apr_proc_create() should do whatever it can to report
+ * failures to the caller of apr_proc_create(), rather than find out in
+ * the child.
+ * @param chk Flag to indicate whether or not extra work should be done
+ * to try to report failures to the caller.
+ * @remark This flag only affects apr_proc_create() on platforms where
+ * fork() is used. This leads to extra overhead in the calling
+ * process, but that may help the application handle such
+ * errors more gracefully.
+ */
+APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr,
+ apr_int32_t chk);
+
#if APR_HAS_FORK
/**
* This is currently the only non-portable call in APR. This executes
Index: include/arch/unix/apr_arch_threadproc.h
===================================================================
RCS file: /home/cvs/apr/include/arch/unix/apr_arch_threadproc.h,v
retrieving revision 1.4
diff -u -r1.4 apr_arch_threadproc.h
--- include/arch/unix/apr_arch_threadproc.h 6 Feb 2003 18:50:30 -0000
1.4
+++ include/arch/unix/apr_arch_threadproc.h 7 Feb 2003 12:56:56 -0000
@@ -135,6 +135,7 @@
struct rlimit *limit_nofile;
#endif
apr_child_errfn_t *errfn;
+ apr_int32_t errchk;
};
#endif /* ! THREAD_PROC_H */
Index: threadproc/unix/proc.c
===================================================================
RCS file: /home/cvs/apr/threadproc/unix/proc.c,v
retrieving revision 1.64
diff -u -r1.64 proc.c
--- threadproc/unix/proc.c 6 Feb 2003 18:50:30 -0000 1.64
+++ threadproc/unix/proc.c 7 Feb 2003 12:56:57 -0000
@@ -302,6 +302,13 @@
return APR_SUCCESS;
}
+APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr,
+ apr_int32_t chk)
+{
+ attr->errchk = chk;
+ return APR_SUCCESS;
+}
+
APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new,
const char *progname,
const char * const *args,
@@ -315,6 +322,32 @@
new->in = attr->parent_in;
new->err = attr->parent_err;
new->out = attr->parent_out;
+
+ if (attr->errchk) {
+ if (attr->currdir) {
+ if (access(attr->currdir, R_OK|X_OK) == -1) {
+ /* chdir() in child wouldn't have worked */
+ return errno;
+ }
+ }
+
+ if (attr->cmdtype == APR_PROGRAM ||
+ attr->cmdtype == APR_PROGRAM_ENV ||
+ *progname == '/') {
+ /* for both of these values of cmdtype, caller must pass
+ * full path, so it is easy to check;
+ * caller can choose to pass full path for other
+ * values of cmdtype
+ */
+ if (access(progname, R_OK|X_OK) == -1) {
+ /* exec*() in child wouldn't have worked */
+ return errno;
+ }
+ }
+ else {
+ /* todo: search PATH for progname then try to access it */
+ }
+ }
if ((new->pid = fork()) < 0) {
return errno;
