tech-toolchain archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: make: cannot vfork() twice - on darwin



On Thu, 22 Apr 2010 22:35:00 +0000, David Holland writes:
>On Thu, Apr 22, 2010 at 03:25:53PM -0700, Simon J. Gerraty wrote:
> > This is "cute", only seems to impact darwin so far.
> > We get an error from vfork() if we've already done it
> > (this happens when trying to export a var that uses :sh in the child).
>
>vforking twice is not allowed.

Yes, but everything but darwin it would seem let's you ;-)


> > Index: main.c
>
>How about centralizing the logic, something like

Sounds reasonable, still need to use the pid trick,
since a parent can vfork many children ok, it is the child that cannot 
vfork - and should not disturb the parent.

Ok the patch is below.  

_BUT_ the change to job.c breaks unit-tests/dotwait 
I haven't worked out why.  The change to Cmd_Exec() is the one that
fixes darwin.  Leaving job.c alone for now.

Index: compat.c
===================================================================
RCS file: /cvsroot/src/usr.bin/make/compat.c,v
retrieving revision 1.77
diff -u -p -r1.77 compat.c
--- compat.c    7 Apr 2010 00:11:27 -0000       1.77
+++ compat.c    22 Apr 2010 23:03:51 -0000
@@ -355,7 +355,7 @@ again:
     /*
      * Fork and execute the single command. If the fork fails, we abort.
      */
-    cpid = vfork();
+    cpid = Fork();
     if (cpid < 0) {
        Fatal("Could not fork");
     }
Index: job.c
===================================================================
RCS file: /cvsroot/src/usr.bin/make/job.c,v
retrieving revision 1.148
diff -u -p -r1.148 job.c
--- job.c       22 Apr 2010 19:11:17 -0000      1.148
+++ job.c       22 Apr 2010 23:03:51 -0000
@@ -1299,7 +1299,7 @@ JobExec(Job *job, char **argv)
     /* Pre-emptively mark job running, pid still zero though */
     job->job_state = JOB_ST_RUNNING;
 
-    cpid = vfork();
+    cpid = Fork();
     if (cpid == -1)
        Punt("Cannot vfork: %s", strerror(errno));
 
Index: main.c
===================================================================
RCS file: /cvsroot/src/usr.bin/make/main.c,v
retrieving revision 1.181
diff -u -p -r1.181 main.c
--- main.c      22 Apr 2010 20:25:16 -0000      1.181
+++ main.c      22 Apr 2010 23:03:52 -0000
@@ -1532,6 +1532,27 @@ Check_Cwd(const char **argv)
     }
 }
 
+/*
+ * We cannot vfork() in a child of vfork()
+ * Most systems do not enforce this but some do.
+ */
+pid_t
+Fork(void)
+{
+    static pid_t mypid = 0;
+    pid_t pid;
+    
+    pid = getpid();
+    if (!mypid)
+       mypid = pid;
+
+    if (pid == mypid)
+       pid = vfork();
+    else
+       pid = fork();
+    return pid;
+}
+
 /*-
  * Cmd_Exec --
  *     Execute the command in cmd, and return the output of that command
@@ -1581,7 +1602,7 @@ Cmd_Exec(const char *cmd, const char **e
     /*
      * Fork
      */
-    switch (cpid = vfork()) {
+    switch (cpid = Fork()) {
     case 0:
        /*
         * Close input side of pipe
Index: nonints.h
===================================================================
RCS file: /cvsroot/src/usr.bin/make/nonints.h,v
retrieving revision 1.58
diff -u -p -r1.58 nonints.h
--- nonints.h   7 Apr 2010 00:11:27 -0000       1.58
+++ nonints.h   22 Apr 2010 23:03:52 -0000
@@ -110,6 +110,7 @@ void For_Run(int);
 void Main_ParseArgLine(const char *);
 void MakeMode(const char *);
 int main(int, char **);
+pid_t Fork(void);
 char *Cmd_Exec(const char *, const char **);
 void Error(const char *, ...) __attribute__((__format__(__printf__, 1, 2)));
 void Fatal(const char *, ...)



Home | Main Index | Thread Index | Old Index