Ver Fonte

* fixed a bunch of cases where ESysEINTR wasn't handled
* call fpexit instead of halt when fpexec fails (the (v)forked child
would otherwise close down a bunch of resources of the parent)
* use vfork instead of fork on Darwin and Solaris (faster)
* fixed indentation (use "svn diff -x -w" to see the important
differences)

git-svn-id: trunk@12925 -

Jonas Maebe há 16 anos atrás
pai
commit
08865be30e
1 ficheiros alterados com 57 adições e 41 exclusões
  1. 57 41
      packages/fcl-process/src/unix/process.inc

+ 57 - 41
packages/fcl-process/src/unix/process.inc

@@ -25,9 +25,13 @@ begin
 end;
 end;
 
 
 Function TProcess.PeekExitStatus : Boolean;
 Function TProcess.PeekExitStatus : Boolean;
-
+var
+  res: cint;
 begin
 begin
-  Result:=fpWaitPid(Handle,pcint(@FExitCode),WNOHANG)=Handle;
+  repeat
+    res:=fpWaitPid(Handle,pcint(@FExitCode),WNOHANG);
+  until (res<>-1) or (fpgeterrno<>ESysEINTR);
+  result:=res=Handle;
   If Result then
   If Result then
     FExitCode:=wexitstatus(FExitCode)
     FExitCode:=wexitstatus(FExitCode)
   else
   else
@@ -236,6 +240,13 @@ begin
   end;
   end;
 end;
 end;
 
 
+Function safefpdup2(fildes, fildes2 : cInt): cInt;
+begin
+  repeat
+    safefpdup2:=fpdup2(fildes,fildes2);
+  until (safefpdup2<>-1) or (fpgeterrno<>ESysEINTR);
+end;
+
 Procedure TProcess.Execute;
 Procedure TProcess.Execute;
 
 
 Var
 Var
@@ -244,6 +255,7 @@ Var
   FEnv     : PPChar;
   FEnv     : PPChar;
   Argv     : PPChar;
   Argv     : PPChar;
   fd       : Integer;
   fd       : Integer;
+  res      : cint;
   FoundName,
   FoundName,
   PName    : String;
   PName    : String;
 
 
@@ -276,50 +288,54 @@ begin
             raise EProcess.CreateFmt(SErrNoSuchProgram,[PName]);
             raise EProcess.CreateFmt(SErrNoSuchProgram,[PName]);
         end;
         end;
 
 
+{$if (defined(DARWIN) or defined(SUNOS))}
+        Pid:=fpvfork;
+{$else}
         Pid:=fpfork;
         Pid:=fpfork;
+{$endif}
         if Pid<0 then
         if Pid<0 then
           Raise EProcess.Create('Failed to Fork process');
           Raise EProcess.Create('Failed to Fork process');
         if (PID>0) then
         if (PID>0) then
           begin
           begin
-          // Parent process. Copy process information.
-          FProcessHandle:=PID;
-          FThreadHandle:=PID;
-          FProcessId:=PID;
-          //FThreadId:=PID;
+            // Parent process. Copy process information.
+            FProcessHandle:=PID;
+            FThreadHandle:=PID;
+            FProcessId:=PID;
+            //FThreadId:=PID;
           end
           end
         else
         else
           begin
           begin
-          { We're in the child }
-          if (FCurrentDirectory<>'') then
-             ChDir(FCurrentDirectory);
-          if PoUsePipes in Options then
-            begin
-            fpclose(HI[peWrite]);
-            fpdup2(HI[peRead],0);
-            fpclose(HO[peRead]);
-            fpdup2(HO[peWrite],1);
-            if (poStdErrToOutPut in Options) then
-              fpdup2(HO[peWrite],2)
-            else
+            { We're in the child }
+            if (FCurrentDirectory<>'') then
+               ChDir(FCurrentDirectory);
+            if PoUsePipes in Options then
               begin
               begin
-              fpclose(HE[peRead]);
-              fpdup2(HE[peWrite],2);
+                FileClose(HI[peWrite]);
+                safefpdup2(HI[peRead],0);
+                FileClose(HO[peRead]);
+                safefpdup2(HO[peWrite],1);
+                if (poStdErrToOutPut in Options) then
+                  safefpdup2(HO[peWrite],2)
+                else
+                  begin
+                    FileClose(HE[peRead]);
+                    safefpdup2(HE[peWrite],2);
+                  end
               end
               end
-            end
-          else if poNoConsole in Options then
-            begin
-            fd:=FileOpen('/dev/null',fmOpenReadWrite);
-            fpdup2(fd,0);
-            fpdup2(fd,1);
-            fpdup2(fd,2);
-            end;
-          if (poRunSuspended in Options) then
-            sigraise(SIGSTOP);
-          if FEnv<>Nil then
-            fpexecve(PName,Argv,Fenv)
-          else
-            fpexecv(PName,argv);
-          Halt(127);
+            else if poNoConsole in Options then
+              begin
+                fd:=FileOpen('/dev/null',fmOpenReadWrite or fmShareDenyNone);
+                safefpdup2(fd,0);
+                safefpdup2(fd,1);
+                safefpdup2(fd,2);
+              end;
+            if (poRunSuspended in Options) then
+              sigraise(SIGSTOP);
+            if FEnv<>Nil then
+              fpexecve(PName,Argv,Fenv)
+            else
+              fpexecv(PName,argv);
+            fpExit(127);
           end
           end
       Finally
       Finally
         FreePcharList(Argv);
         FreePcharList(Argv);
@@ -331,11 +347,11 @@ begin
   Finally
   Finally
     if POUsePipes in FProcessOptions then
     if POUsePipes in FProcessOptions then
       begin
       begin
-      FileClose(HO[peWrite]);
-      FileClose(HI[peRead]);
-      if Not (poStdErrToOutPut in FProcessOptions) then
-        FileClose(HE[peWrite]);
-      CreateStreams(HI[peWrite],HO[peRead],HE[peRead]);
+        FileClose(HO[peWrite]);
+        FileClose(HI[peRead]);
+        if Not (poStdErrToOutPut in FProcessOptions) then
+          FileClose(HE[peWrite]);
+        CreateStreams(HI[peWrite],HO[peRead],HE[peRead]);
       end;
       end;
   end;
   end;
   FRunning:=True;
   FRunning:=True;