summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authorGurusamy Sarathy <gsar@cpan.org>2001-07-20 18:38:48 +0000
committerGurusamy Sarathy <gsar@cpan.org>2001-07-20 18:38:48 +0000
commit52e18b1f277416a33dff2c066a83fdab0520a2d7 (patch)
tree0d35a4f042171ce3c05667667ca19d69d060a292 /util.c
parent9046a8ae3aad1f7eda5affd38301ac2313201634 (diff)
downloadperl-52e18b1f277416a33dff2c066a83fdab0520a2d7.tar.gz
Make perl fork()-safe (in a slightly limited way) even on
platforms that don't have pthread_atfork() (extension of the fix in change#11151). Note that this will not help extensions that call fork() directly in C, or that link to libraries that call fork() directly. Such cases must be fixed to either call PerlProc_fork(), or call atfork_lock() in parent before the calling the function that forks and call atfork_unlock() in both parent and child immediately after the fork(). (There are no worries if C code calls exec() in the child immediately after a fork(). Only cases where the child calls perl's API functions (including New()) after the fork() are problematic.) This change also eliminates the use of vfork() from perl, since all such uses were violating the severe restrictions on modifying the state of the process between the vfork() and the exec(). This is a modified version of patches suggested by Abhijit Menon-Sen and Richard Soderberg. p4raw-link: @11151 on //depot/perl: 50dd6e574ff39b609595ddb16b2fe9f625a26f8c p4raw-id: //depot/perl@11423
Diffstat (limited to 'util.c')
-rw-r--r--util.c66
1 files changed, 51 insertions, 15 deletions
diff --git a/util.c b/util.c
index e01e836cd1..5262e6a2ed 100644
--- a/util.c
+++ b/util.c
@@ -26,17 +26,6 @@
#endif
#endif
-#ifdef I_VFORK
-# include <vfork.h>
-#endif
-
-/* Put this after #includes because fork and vfork prototypes may
- conflict.
-*/
-#ifndef HAS_VFORK
-# define vfork fork
-#endif
-
#ifdef I_SYS_WAIT
# include <sys/wait.h>
#endif
@@ -1858,7 +1847,7 @@ Perl_my_popen_list(pTHX_ char *mode, int n, SV **args)
/* Try for another pipe pair for error return */
if (PerlProc_pipe(pp) >= 0)
did_pipes = 1;
- while ((pid = vfork()) < 0) {
+ while ((pid = PerlProc_fork()) < 0) {
if (errno != EAGAIN) {
PerlLIO_close(p[This]);
if (did_pipes) {
@@ -1910,7 +1899,7 @@ Perl_my_popen_list(pTHX_ char *mode, int n, SV **args)
#undef THAT
}
/* Parent */
- do_execfree(); /* free any memory malloced by child on vfork */
+ do_execfree(); /* free any memory malloced by child on fork */
/* Close child's end of pipe */
PerlLIO_close(p[that]);
if (did_pipes)
@@ -1991,7 +1980,7 @@ Perl_my_popen(pTHX_ char *cmd, char *mode)
return Nullfp;
if (doexec && PerlProc_pipe(pp) >= 0)
did_pipes = 1;
- while ((pid = (doexec?vfork():fork())) < 0) {
+ while ((pid = PerlProc_fork()) < 0) {
if (errno != EAGAIN) {
PerlLIO_close(p[This]);
if (did_pipes) {
@@ -2052,7 +2041,7 @@ Perl_my_popen(pTHX_ char *cmd, char *mode)
#undef THIS
#undef THAT
}
- do_execfree(); /* free any memory malloced by child on vfork */
+ do_execfree(); /* free any memory malloced by child on fork */
PerlLIO_close(p[that]);
if (did_pipes)
PerlLIO_close(pp[1]);
@@ -2127,6 +2116,53 @@ Perl_my_popen(pTHX_ char *cmd, char *mode)
#endif /* !DOSISH */
+/* this is called in parent before the fork() */
+void
+Perl_atfork_lock(void)
+{
+#if defined(USE_THREADS) || defined(USE_ITHREADS)
+ /* locks must be held in locking order (if any) */
+# ifdef MYMALLOC
+ MUTEX_LOCK(&PL_malloc_mutex);
+# endif
+ OP_REFCNT_LOCK;
+#endif
+}
+
+/* this is called in both parent and child after the fork() */
+void
+Perl_atfork_unlock(void)
+{
+#if defined(USE_THREADS) || defined(USE_ITHREADS)
+ /* locks must be released in same order as in atfork_lock() */
+# ifdef MYMALLOC
+ MUTEX_UNLOCK(&PL_malloc_mutex);
+# endif
+ OP_REFCNT_UNLOCK;
+#endif
+}
+
+Pid_t
+Perl_my_fork(void)
+{
+#if defined(HAS_FORK)
+ Pid_t pid;
+#if (defined(USE_THREADS) || defined(USE_ITHREADS)) && !defined(HAS_PTHREAD_ATFORK)
+ atfork_lock();
+ pid = fork();
+ atfork_unlock();
+#else
+ /* atfork_lock() and atfork_unlock() are installed as pthread_atfork()
+ * handlers elsewhere in the code */
+ pid = fork();
+#endif
+ return pid;
+#else
+ /* this "canna happen" since nothing should be calling here if !HAS_FORK */
+ Perl_croak_nocontext("fork() not available");
+#endif /* HAS_FORK */
+}
+
#ifdef DUMP_FDS
void
Perl_dump_fds(pTHX_ char *s)