1 /*=========================================================================
3 Program: KWSys - Kitware System Library
4 Module: $RCSfile: ProcessWin32.c,v $
6 Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
7 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the above copyright notices for more information.
13 =========================================================================*/
14 #include "kwsysPrivate.h"
15 #include KWSYS_HEADER(Process.h)
16 #include KWSYS_HEADER(System.h)
18 /* Work-around CMake dependency scanning limitation. This must
19 duplicate the above list of headers. */
21 # include "Process.h.in"
22 # include "System.h.in"
27 Implementation for Windows
29 On windows, a thread is created to wait for data on each pipe. The
30 threads are synchronized with the main thread to simulate the use of
31 a UNIX-style select system call.
33 On Windows9x platforms, a small WIN32 console application is spawned
34 in-between the calling process and the actual child to be executed.
35 This is to work-around a problem with connecting pipes from WIN16
36 console applications to WIN32 applications.
38 For more information, please check Microsoft Knowledge Base Articles
44 #pragma warning (push, 1)
46 #include <windows.h> /* Windows API */
47 #include <string.h> /* strlen, strdup */
48 #include <stdio.h> /* sprintf */
49 #include <io.h> /* _unlink */
51 #define _unlink unlink
55 #define _MAX_FNAME 4096
58 #define _MAX_PATH 4096
63 #pragma warning (disable: 4514)
64 #pragma warning (disable: 4706)
67 #if defined(__BORLANDC__)
68 # pragma warn -8004 /* assigned a value that is never used */
69 # pragma warn -8060 /* Assignment inside if() condition. */
72 /* There are pipes for the process pipeline's stdout and stderr. */
73 #define KWSYSPE_PIPE_COUNT 2
74 #define KWSYSPE_PIPE_STDOUT 0
75 #define KWSYSPE_PIPE_STDERR 1
77 /* The maximum amount to read from a pipe at a time. */
78 #define KWSYSPE_PIPE_BUFFER_SIZE 1024
80 /* Debug output macro. */
82 # define KWSYSPE_DEBUG(x) \
84 (void*)cp == (void*)0x00226DE0? \
86 fprintf(stderr, "%d/%p/%d ", (int)GetCurrentProcessId(), cp, __LINE__), \
93 # define KWSYSPE_DEBUG(x) (void)1
96 #define kwsysEncodedWriteArrayProcessFwd9x kwsys_ns(EncodedWriteArrayProcessFwd9x)
98 typedef LARGE_INTEGER kwsysProcessTime
;
100 typedef struct kwsysProcessCreateInformation_s
102 /* Windows child startup control data. */
103 STARTUPINFO StartupInfo
;
105 /* Special error reporting pipe for Win9x forwarding executable. */
106 HANDLE ErrorPipeRead
;
107 HANDLE ErrorPipeWrite
;
108 } kwsysProcessCreateInformation
;
110 /*--------------------------------------------------------------------------*/
111 typedef struct kwsysProcessPipeData_s kwsysProcessPipeData
;
112 static DWORD WINAPI
kwsysProcessPipeThreadRead(LPVOID ptd
);
113 static void kwsysProcessPipeThreadReadPipe(kwsysProcess
* cp
,
114 kwsysProcessPipeData
* td
);
115 static DWORD WINAPI
kwsysProcessPipeThreadWake(LPVOID ptd
);
116 static void kwsysProcessPipeThreadWakePipe(kwsysProcess
* cp
,
117 kwsysProcessPipeData
* td
);
118 static int kwsysProcessInitialize(kwsysProcess
* cp
);
119 static int kwsysProcessCreate(kwsysProcess
* cp
, int index
,
120 kwsysProcessCreateInformation
* si
,
122 static void kwsysProcessDestroy(kwsysProcess
* cp
, int event
);
123 static int kwsysProcessSetupOutputPipeFile(PHANDLE handle
, const char* name
);
124 static int kwsysProcessSetupSharedPipe(DWORD nStdHandle
, PHANDLE handle
);
125 static int kwsysProcessSetupPipeNative(PHANDLE handle
, HANDLE p
[2],
127 static void kwsysProcessCleanupHandle(PHANDLE h
);
128 static void kwsysProcessCleanupHandleSafe(PHANDLE h
, DWORD nStdHandle
);
129 static void kwsysProcessCleanup(kwsysProcess
* cp
, int error
);
130 static void kwsysProcessCleanErrorMessage(kwsysProcess
* cp
);
131 static int kwsysProcessComputeCommandLength(kwsysProcess
* cp
,
132 char const* const* command
);
133 static void kwsysProcessComputeCommandLine(kwsysProcess
* cp
,
134 char const* const* command
,
136 static int kwsysProcessGetTimeoutTime(kwsysProcess
* cp
, double* userTimeout
,
137 kwsysProcessTime
* timeoutTime
);
138 static int kwsysProcessGetTimeoutLeft(kwsysProcessTime
* timeoutTime
,
140 kwsysProcessTime
* timeoutLength
);
141 static kwsysProcessTime
kwsysProcessTimeGetCurrent(void);
142 static DWORD
kwsysProcessTimeToDWORD(kwsysProcessTime t
);
143 static double kwsysProcessTimeToDouble(kwsysProcessTime t
);
144 static kwsysProcessTime
kwsysProcessTimeFromDouble(double d
);
145 static int kwsysProcessTimeLess(kwsysProcessTime in1
, kwsysProcessTime in2
);
146 static kwsysProcessTime
kwsysProcessTimeAdd(kwsysProcessTime in1
, kwsysProcessTime in2
);
147 static kwsysProcessTime
kwsysProcessTimeSubtract(kwsysProcessTime in1
, kwsysProcessTime in2
);
148 static void kwsysProcessSetExitException(kwsysProcess
* cp
, int code
);
149 static void kwsysProcessKillTree(int pid
);
150 static void kwsysProcessDisablePipeThreads(kwsysProcess
* cp
);
151 extern kwsysEXPORT
int kwsysEncodedWriteArrayProcessFwd9x(const char* fname
);
153 /*--------------------------------------------------------------------------*/
154 /* A structure containing synchronization data for each thread. */
155 typedef struct kwsysProcessPipeSync_s kwsysProcessPipeSync
;
156 struct kwsysProcessPipeSync_s
158 /* Handle to the thread. */
161 /* Semaphore indicating to the thread that a process has started. */
164 /* Semaphore indicating to the thread that it should begin work. */
167 /* Semaphore indicating thread has reset for another process. */
171 /*--------------------------------------------------------------------------*/
172 /* A structure containing data for each pipe's threads. */
173 struct kwsysProcessPipeData_s
175 /* ------------- Data managed per instance of kwsysProcess ------------- */
177 /* Synchronization data for reading thread. */
178 kwsysProcessPipeSync Reader
;
180 /* Synchronization data for waking thread. */
181 kwsysProcessPipeSync Waker
;
183 /* Index of this pipe. */
186 /* The kwsysProcess instance owning this pipe. */
187 kwsysProcess
* Process
;
189 /* ------------- Data managed per call to Execute ------------- */
191 /* Buffer for data read in this pipe's thread. */
192 char DataBuffer
[KWSYSPE_PIPE_BUFFER_SIZE
];
194 /* The length of the data stored in the buffer. */
197 /* Whether the pipe has been closed. */
200 /* Handle for the read end of this pipe. */
203 /* Handle for the write end of this pipe. */
207 /*--------------------------------------------------------------------------*/
208 /* Structure containing data used to implement the child's execution. */
209 struct kwsysProcess_s
211 /* ------------- Data managed per instance of kwsysProcess ------------- */
213 /* The status of the process structure. */
216 /* The command lines to execute. */
218 int NumberOfCommands
;
220 /* The exit code of each command. */
221 DWORD
* CommandExitCodes
;
223 /* The working directory for the child process. */
224 char* WorkingDirectory
;
226 /* Whether to create the child as a detached process. */
229 /* Whether the child was created as a detached process. */
232 /* Whether to hide the child process's window. */
235 /* Whether to treat command lines as verbatim. */
238 /* On Win9x platforms, the path to the forwarding executable. */
241 /* On Win9x platforms, the resume event for the forwarding executable. */
242 HANDLE Win9xResumeEvent
;
244 /* On Win9x platforms, the kill event for the forwarding executable. */
245 HANDLE Win9xKillEvent
;
247 /* Mutex to protect the shared index used by threads to report data. */
248 HANDLE SharedIndexMutex
;
250 /* Semaphore used by threads to signal data ready. */
253 /* Whether we are currently deleting this kwsysProcess instance. */
256 /* Data specific to each pipe and its thread. */
257 kwsysProcessPipeData Pipe
[KWSYSPE_PIPE_COUNT
];
259 /* Name of files to which stdin and stdout pipes are attached. */
261 char* PipeFileSTDOUT
;
262 char* PipeFileSTDERR
;
264 /* Whether each pipe is shared with the parent process. */
266 int PipeSharedSTDOUT
;
267 int PipeSharedSTDERR
;
269 /* Native pipes provided by the user. */
270 HANDLE PipeNativeSTDIN
[2];
271 HANDLE PipeNativeSTDOUT
[2];
272 HANDLE PipeNativeSTDERR
[2];
274 /* Handle to automatically delete the Win9x forwarding executable. */
277 /* ------------- Data managed per call to Execute ------------- */
279 /* The exceptional behavior that terminated the process, if any. */
282 /* The process exit code. */
285 /* The process return code, if any. */
288 /* Index of last pipe to report data, if any. */
291 /* Index shared by threads to report data. */
294 /* The timeout length. */
297 /* Time at which the child started. */
298 kwsysProcessTime StartTime
;
300 /* Time at which the child will timeout. Negative for no timeout. */
301 kwsysProcessTime TimeoutTime
;
303 /* Flag for whether the process was killed. */
306 /* Flag for whether the timeout expired. */
309 /* Flag for whether the process has terminated. */
312 /* The number of pipes still open during execution and while waiting
313 for pipes to close after process termination. */
316 /* Buffer for error messages (possibly from Win9x child). */
317 char ErrorMessage
[KWSYSPE_PIPE_BUFFER_SIZE
+1];
319 /* Description for the ExitException. */
320 char ExitExceptionString
[KWSYSPE_PIPE_BUFFER_SIZE
+1];
322 /* Windows process information data. */
323 PROCESS_INFORMATION
* ProcessInformation
;
325 /* Data and process termination events for which to wait. */
326 PHANDLE ProcessEvents
;
327 int ProcessEventsLength
;
329 /* Real working directory of our own process. */
330 DWORD RealWorkingDirectoryLength
;
331 char* RealWorkingDirectory
;
334 /*--------------------------------------------------------------------------*/
335 kwsysProcess
* kwsysProcess_New(void)
339 /* Process control structure. */
342 /* Path to Win9x forwarding executable. */
345 /* Windows version number data. */
348 /* Allocate a process control structure. */
349 cp
= (kwsysProcess
*)malloc(sizeof(kwsysProcess
));
352 /* Could not allocate memory for the control structure. */
355 ZeroMemory(cp
, sizeof(*cp
));
357 /* Share stdin with the parent process by default. */
358 cp
->PipeSharedSTDIN
= 1;
360 /* Set initial status. */
361 cp
->State
= kwsysProcess_State_Starting
;
363 /* Choose a method of running the child based on version of
365 ZeroMemory(&osv
, sizeof(osv
));
366 osv
.dwOSVersionInfoSize
= sizeof(osv
);
368 if(osv
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
)
370 /* This is Win9x. We need the console forwarding executable to
371 work-around a Windows 9x bug. */
372 char fwdName
[_MAX_FNAME
+1] = "";
373 char tempDir
[_MAX_PATH
+1] = "";
375 /* We will try putting the executable in the system temp
376 directory. Note that the returned path already has a trailing
378 DWORD length
= GetTempPath(_MAX_PATH
+1, tempDir
);
380 /* Construct the executable name from the process id and kwsysProcess
381 instance. This should be unique. */
382 sprintf(fwdName
, KWSYS_NAMESPACE_STRING
"pew9xfwd_%ld_%p.exe",
383 GetCurrentProcessId(), cp
);
385 /* If we have a temp directory, use it. */
386 if(length
> 0 && length
<= _MAX_PATH
)
388 /* Allocate a buffer to hold the forwarding executable path. */
389 size_t tdlen
= strlen(tempDir
);
390 win9x
= (char*)malloc(tdlen
+ strlen(fwdName
) + 2);
393 kwsysProcess_Delete(cp
);
397 /* Construct the full path to the forwarding executable. */
398 sprintf(win9x
, "%s%s", tempDir
, fwdName
);
401 /* If we found a place to put the forwarding executable, try to
405 if(!kwsysEncodedWriteArrayProcessFwd9x(win9x
))
407 /* Failed to create forwarding executable. Give up. */
409 kwsysProcess_Delete(cp
);
413 /* Get a handle to the file that will delete it when closed. */
414 cp
->Win9xHandle
= CreateFile(win9x
, GENERIC_READ
, FILE_SHARE_READ
, 0,
415 OPEN_EXISTING
, FILE_FLAG_DELETE_ON_CLOSE
, 0);
416 if(cp
->Win9xHandle
== INVALID_HANDLE_VALUE
)
418 /* We were not able to get a read handle for the forwarding
419 executable. It will not be deleted properly. Give up. */
422 kwsysProcess_Delete(cp
);
428 /* Failed to find a place to put forwarding executable. */
429 kwsysProcess_Delete(cp
);
434 /* Save the path to the forwarding executable. */
437 /* Initially no thread owns the mutex. Initialize semaphore to 1. */
438 if(!(cp
->SharedIndexMutex
= CreateSemaphore(0, 1, 1, 0)))
440 kwsysProcess_Delete(cp
);
444 /* Initially no data are available. Initialize semaphore to 0. */
445 if(!(cp
->Full
= CreateSemaphore(0, 0, 1, 0)))
447 kwsysProcess_Delete(cp
);
453 SECURITY_ATTRIBUTES sa
;
454 ZeroMemory(&sa
, sizeof(sa
));
455 sa
.nLength
= sizeof(sa
);
456 sa
.bInheritHandle
= TRUE
;
458 /* Create an event to tell the forwarding executable to resume the
460 if(!(cp
->Win9xResumeEvent
= CreateEvent(&sa
, TRUE
, 0, 0)))
462 kwsysProcess_Delete(cp
);
466 /* Create an event to tell the forwarding executable to kill the
468 if(!(cp
->Win9xKillEvent
= CreateEvent(&sa
, TRUE
, 0, 0)))
470 kwsysProcess_Delete(cp
);
475 /* Create the thread to read each pipe. */
476 for(i
=0; i
< KWSYSPE_PIPE_COUNT
; ++i
)
480 /* Assign the thread its index. */
481 cp
->Pipe
[i
].Index
= i
;
483 /* Give the thread a pointer back to the kwsysProcess instance. */
484 cp
->Pipe
[i
].Process
= cp
;
486 /* No process is yet running. Initialize semaphore to 0. */
487 if(!(cp
->Pipe
[i
].Reader
.Ready
= CreateSemaphore(0, 0, 1, 0)))
489 kwsysProcess_Delete(cp
);
493 /* The pipe is not yet reset. Initialize semaphore to 0. */
494 if(!(cp
->Pipe
[i
].Reader
.Reset
= CreateSemaphore(0, 0, 1, 0)))
496 kwsysProcess_Delete(cp
);
500 /* The thread's buffer is initially empty. Initialize semaphore to 1. */
501 if(!(cp
->Pipe
[i
].Reader
.Go
= CreateSemaphore(0, 1, 1, 0)))
503 kwsysProcess_Delete(cp
);
507 /* Create the reading thread. It will block immediately. The
508 thread will not make deeply nested calls, so we need only a
510 if(!(cp
->Pipe
[i
].Reader
.Thread
= CreateThread(0, 1024,
511 kwsysProcessPipeThreadRead
,
512 &cp
->Pipe
[i
], 0, &dummy
)))
514 kwsysProcess_Delete(cp
);
518 /* No process is yet running. Initialize semaphore to 0. */
519 if(!(cp
->Pipe
[i
].Waker
.Ready
= CreateSemaphore(0, 0, 1, 0)))
521 kwsysProcess_Delete(cp
);
525 /* The pipe is not yet reset. Initialize semaphore to 0. */
526 if(!(cp
->Pipe
[i
].Waker
.Reset
= CreateSemaphore(0, 0, 1, 0)))
528 kwsysProcess_Delete(cp
);
532 /* The waker should not wake immediately. Initialize semaphore to 0. */
533 if(!(cp
->Pipe
[i
].Waker
.Go
= CreateSemaphore(0, 0, 1, 0)))
535 kwsysProcess_Delete(cp
);
539 /* Create the waking thread. It will block immediately. The
540 thread will not make deeply nested calls, so we need only a
542 if(!(cp
->Pipe
[i
].Waker
.Thread
= CreateThread(0, 1024,
543 kwsysProcessPipeThreadWake
,
544 &cp
->Pipe
[i
], 0, &dummy
)))
546 kwsysProcess_Delete(cp
);
554 /*--------------------------------------------------------------------------*/
555 void kwsysProcess_Delete(kwsysProcess
* cp
)
559 /* Make sure we have an instance. */
565 /* If the process is executing, wait for it to finish. */
566 if(cp
->State
== kwsysProcess_State_Executing
)
570 kwsysProcess_Disown(cp
);
574 kwsysProcess_WaitForExit(cp
, 0);
578 /* We are deleting the kwsysProcess instance. */
581 /* Terminate each of the threads. */
582 for(i
=0; i
< KWSYSPE_PIPE_COUNT
; ++i
)
584 /* Terminate this reading thread. */
585 if(cp
->Pipe
[i
].Reader
.Thread
)
587 /* Signal the thread we are ready for it. It will terminate
588 immediately since Deleting is set. */
589 ReleaseSemaphore(cp
->Pipe
[i
].Reader
.Ready
, 1, 0);
591 /* Wait for the thread to exit. */
592 WaitForSingleObject(cp
->Pipe
[i
].Reader
.Thread
, INFINITE
);
594 /* Close the handle to the thread. */
595 kwsysProcessCleanupHandle(&cp
->Pipe
[i
].Reader
.Thread
);
598 /* Terminate this waking thread. */
599 if(cp
->Pipe
[i
].Waker
.Thread
)
601 /* Signal the thread we are ready for it. It will terminate
602 immediately since Deleting is set. */
603 ReleaseSemaphore(cp
->Pipe
[i
].Waker
.Ready
, 1, 0);
605 /* Wait for the thread to exit. */
606 WaitForSingleObject(cp
->Pipe
[i
].Waker
.Thread
, INFINITE
);
608 /* Close the handle to the thread. */
609 kwsysProcessCleanupHandle(&cp
->Pipe
[i
].Waker
.Thread
);
612 /* Cleanup the pipe's semaphores. */
613 kwsysProcessCleanupHandle(&cp
->Pipe
[i
].Reader
.Ready
);
614 kwsysProcessCleanupHandle(&cp
->Pipe
[i
].Reader
.Go
);
615 kwsysProcessCleanupHandle(&cp
->Pipe
[i
].Reader
.Reset
);
616 kwsysProcessCleanupHandle(&cp
->Pipe
[i
].Waker
.Ready
);
617 kwsysProcessCleanupHandle(&cp
->Pipe
[i
].Waker
.Go
);
618 kwsysProcessCleanupHandle(&cp
->Pipe
[i
].Waker
.Reset
);
621 /* Close the shared semaphores. */
622 kwsysProcessCleanupHandle(&cp
->SharedIndexMutex
);
623 kwsysProcessCleanupHandle(&cp
->Full
);
625 /* Close the Win9x resume and kill event handles. */
628 kwsysProcessCleanupHandle(&cp
->Win9xResumeEvent
);
629 kwsysProcessCleanupHandle(&cp
->Win9xKillEvent
);
633 kwsysProcess_SetCommand(cp
, 0);
634 kwsysProcess_SetWorkingDirectory(cp
, 0);
635 kwsysProcess_SetPipeFile(cp
, kwsysProcess_Pipe_STDIN
, 0);
636 kwsysProcess_SetPipeFile(cp
, kwsysProcess_Pipe_STDOUT
, 0);
637 kwsysProcess_SetPipeFile(cp
, kwsysProcess_Pipe_STDERR
, 0);
638 if(cp
->CommandExitCodes
)
640 free(cp
->CommandExitCodes
);
644 /* Close our handle to the forwarding executable file. This will
645 cause it to be deleted. */
646 kwsysProcessCleanupHandle(&cp
->Win9xHandle
);
651 /*--------------------------------------------------------------------------*/
652 int kwsysProcess_SetCommand(kwsysProcess
* cp
, char const* const* command
)
659 for(i
=0; i
< cp
->NumberOfCommands
; ++i
)
661 free(cp
->Commands
[i
]);
663 cp
->NumberOfCommands
= 0;
671 return kwsysProcess_AddCommand(cp
, command
);
676 /*--------------------------------------------------------------------------*/
677 int kwsysProcess_AddCommand(kwsysProcess
* cp
, char const* const* command
)
679 int newNumberOfCommands
;
682 /* Make sure we have a command to add. */
683 if(!cp
|| !command
|| !*command
)
688 /* Allocate a new array for command pointers. */
689 newNumberOfCommands
= cp
->NumberOfCommands
+ 1;
690 if(!(newCommands
= (char**)malloc(sizeof(char*) * newNumberOfCommands
)))
696 /* Copy any existing commands into the new array. */
699 for(i
=0; i
< cp
->NumberOfCommands
; ++i
)
701 newCommands
[i
] = cp
->Commands
[i
];
705 /* We need to construct a single string representing the command
706 and its arguments. We will surround each argument containing
707 spaces with double-quotes. Inside a double-quoted argument, we
708 need to escape double-quotes and all backslashes before them.
709 We also need to escape backslashes at the end of an argument
710 because they come before the closing double-quote for the
713 /* First determine the length of the final string. */
714 int length
= kwsysProcessComputeCommandLength(cp
, command
);
716 /* Allocate enough space for the command. We do not need an extra
717 byte for the terminating null because we allocated a space for
718 the first argument that we will not use. */
719 newCommands
[cp
->NumberOfCommands
] = (char*)malloc(length
);
720 if(!newCommands
[cp
->NumberOfCommands
])
727 /* Construct the command line in the allocated buffer. */
728 kwsysProcessComputeCommandLine(cp
, command
,
729 newCommands
[cp
->NumberOfCommands
]);
732 /* Save the new array of commands. */
734 cp
->Commands
= newCommands
;
735 cp
->NumberOfCommands
= newNumberOfCommands
;
739 /*--------------------------------------------------------------------------*/
740 void kwsysProcess_SetTimeout(kwsysProcess
* cp
, double timeout
)
746 cp
->Timeout
= timeout
;
753 /*--------------------------------------------------------------------------*/
754 int kwsysProcess_SetWorkingDirectory(kwsysProcess
* cp
, const char* dir
)
760 if(cp
->WorkingDirectory
)
762 free(cp
->WorkingDirectory
);
763 cp
->WorkingDirectory
= 0;
767 /* We must convert the working directory to a full path. */
768 DWORD length
= GetFullPathName(dir
, 0, 0, 0);
771 cp
->WorkingDirectory
= (char*)malloc(length
);
772 if(!cp
->WorkingDirectory
)
776 if(!GetFullPathName(dir
, length
, cp
->WorkingDirectory
, 0))
778 free(cp
->WorkingDirectory
);
779 cp
->WorkingDirectory
= 0;
787 /*--------------------------------------------------------------------------*/
788 int kwsysProcess_SetPipeFile(kwsysProcess
* cp
, int pipe
, const char* file
)
797 case kwsysProcess_Pipe_STDIN
: pfile
= &cp
->PipeFileSTDIN
; break;
798 case kwsysProcess_Pipe_STDOUT
: pfile
= &cp
->PipeFileSTDOUT
; break;
799 case kwsysProcess_Pipe_STDERR
: pfile
= &cp
->PipeFileSTDERR
; break;
809 *pfile
= malloc(strlen(file
)+1);
814 strcpy(*pfile
, file
);
817 /* If we are redirecting the pipe, do not share it or use a native
821 kwsysProcess_SetPipeNative(cp
, pipe
, 0);
822 kwsysProcess_SetPipeShared(cp
, pipe
, 0);
828 /*--------------------------------------------------------------------------*/
829 void kwsysProcess_SetPipeShared(kwsysProcess
* cp
, int pipe
, int shared
)
838 case kwsysProcess_Pipe_STDIN
: cp
->PipeSharedSTDIN
= shared
?1:0; break;
839 case kwsysProcess_Pipe_STDOUT
: cp
->PipeSharedSTDOUT
= shared
?1:0; break;
840 case kwsysProcess_Pipe_STDERR
: cp
->PipeSharedSTDERR
= shared
?1:0; break;
844 /* If we are sharing the pipe, do not redirect it to a file or use a
848 kwsysProcess_SetPipeFile(cp
, pipe
, 0);
849 kwsysProcess_SetPipeNative(cp
, pipe
, 0);
853 /*--------------------------------------------------------------------------*/
854 void kwsysProcess_SetPipeNative(kwsysProcess
* cp
, int pipe
, HANDLE p
[2])
856 HANDLE
* pPipeNative
= 0;
865 case kwsysProcess_Pipe_STDIN
: pPipeNative
= cp
->PipeNativeSTDIN
; break;
866 case kwsysProcess_Pipe_STDOUT
: pPipeNative
= cp
->PipeNativeSTDOUT
; break;
867 case kwsysProcess_Pipe_STDERR
: pPipeNative
= cp
->PipeNativeSTDERR
; break;
871 /* Copy the native pipe handles provided. */
874 pPipeNative
[0] = p
[0];
875 pPipeNative
[1] = p
[1];
883 /* If we are using a native pipe, do not share it or redirect it to
887 kwsysProcess_SetPipeFile(cp
, pipe
, 0);
888 kwsysProcess_SetPipeShared(cp
, pipe
, 0);
892 /*--------------------------------------------------------------------------*/
893 int kwsysProcess_GetOption(kwsysProcess
* cp
, int optionId
)
902 case kwsysProcess_Option_Detach
: return cp
->OptionDetach
;
903 case kwsysProcess_Option_HideWindow
: return cp
->HideWindow
;
904 case kwsysProcess_Option_Verbatim
: return cp
->Verbatim
;
909 /*--------------------------------------------------------------------------*/
910 void kwsysProcess_SetOption(kwsysProcess
* cp
, int optionId
, int value
)
919 case kwsysProcess_Option_Detach
: cp
->OptionDetach
= value
; break;
920 case kwsysProcess_Option_HideWindow
: cp
->HideWindow
= value
; break;
921 case kwsysProcess_Option_Verbatim
: cp
->Verbatim
= value
; break;
926 /*--------------------------------------------------------------------------*/
927 int kwsysProcess_GetState(kwsysProcess
* cp
)
929 return cp
? cp
->State
: kwsysProcess_State_Error
;
932 /*--------------------------------------------------------------------------*/
933 int kwsysProcess_GetExitException(kwsysProcess
* cp
)
935 return cp
? cp
->ExitException
: kwsysProcess_Exception_Other
;
938 /*--------------------------------------------------------------------------*/
939 int kwsysProcess_GetExitValue(kwsysProcess
* cp
)
941 return cp
? cp
->ExitValue
: -1;
944 /*--------------------------------------------------------------------------*/
945 int kwsysProcess_GetExitCode(kwsysProcess
* cp
)
947 return cp
? cp
->ExitCode
: 0;
950 /*--------------------------------------------------------------------------*/
951 const char* kwsysProcess_GetErrorString(kwsysProcess
* cp
)
955 return "Process management structure could not be allocated";
957 else if(cp
->State
== kwsysProcess_State_Error
)
959 return cp
->ErrorMessage
;
964 /*--------------------------------------------------------------------------*/
965 const char* kwsysProcess_GetExceptionString(kwsysProcess
* cp
)
969 return "GetExceptionString called with NULL process management structure";
971 else if(cp
->State
== kwsysProcess_State_Exception
)
973 return cp
->ExitExceptionString
;
975 return "No exception";
978 /*--------------------------------------------------------------------------*/
979 void kwsysProcess_Execute(kwsysProcess
* cp
)
983 /* Child startup control data. */
984 kwsysProcessCreateInformation si
;
986 /* Do not execute a second time. */
987 if(!cp
|| cp
->State
== kwsysProcess_State_Executing
)
992 /* Initialize the control structure for a new process. */
993 if(!kwsysProcessInitialize(cp
))
995 strcpy(cp
->ErrorMessage
, "Out of memory");
996 cp
->State
= kwsysProcess_State_Error
;
1000 /* Save the real working directory of this process and change to
1001 the working directory for the child processes. This is needed
1002 to make pipe file paths evaluate correctly. */
1003 if(cp
->WorkingDirectory
)
1005 if(!GetCurrentDirectory(cp
->RealWorkingDirectoryLength
,
1006 cp
->RealWorkingDirectory
))
1008 kwsysProcessCleanup(cp
, 1);
1011 SetCurrentDirectory(cp
->WorkingDirectory
);
1014 /* Reset the Win9x resume and kill events. */
1017 if(!ResetEvent(cp
->Win9xResumeEvent
))
1019 kwsysProcessCleanup(cp
, 1);
1022 if(!ResetEvent(cp
->Win9xKillEvent
))
1024 kwsysProcessCleanup(cp
, 1);
1029 /* Initialize startup info data. */
1030 ZeroMemory(&si
, sizeof(si
));
1031 si
.StartupInfo
.cb
= sizeof(si
.StartupInfo
);
1033 /* Decide whether a child window should be shown. */
1034 si
.StartupInfo
.dwFlags
|= STARTF_USESHOWWINDOW
;
1035 si
.StartupInfo
.wShowWindow
=
1036 (unsigned short)(cp
->HideWindow
?SW_HIDE
:SW_SHOWDEFAULT
);
1038 /* Connect the child's output pipes to the threads. */
1039 si
.StartupInfo
.dwFlags
|= STARTF_USESTDHANDLES
;
1041 /* Create stderr pipe to be shared by all processes in the pipeline.
1042 Neither end is directly inherited. */
1043 if(!CreatePipe(&cp
->Pipe
[KWSYSPE_PIPE_STDERR
].Read
,
1044 &cp
->Pipe
[KWSYSPE_PIPE_STDERR
].Write
, 0, 0))
1046 kwsysProcessCleanup(cp
, 1);
1050 /* Create an inherited duplicate of the write end, but do not
1051 close the non-inherited version. We need to keep it open
1052 to use in waking up the pipe threads. */
1053 if(!DuplicateHandle(GetCurrentProcess(), cp
->Pipe
[KWSYSPE_PIPE_STDERR
].Write
,
1054 GetCurrentProcess(), &si
.StartupInfo
.hStdError
,
1055 0, TRUE
, DUPLICATE_SAME_ACCESS
))
1057 kwsysProcessCleanup(cp
, 1);
1058 kwsysProcessCleanupHandle(&si
.StartupInfo
.hStdError
);
1062 /* Replace the stderr pipe with a file if requested. In this case
1063 the pipe thread will still run but never report data. */
1064 if(cp
->PipeFileSTDERR
)
1066 if(!kwsysProcessSetupOutputPipeFile(&si
.StartupInfo
.hStdError
,
1067 cp
->PipeFileSTDERR
))
1069 kwsysProcessCleanup(cp
, 1);
1070 kwsysProcessCleanupHandle(&si
.StartupInfo
.hStdError
);
1075 /* Replace the stderr pipe with the parent process's if requested.
1076 In this case the pipe thread will still run but never report
1078 if(cp
->PipeSharedSTDERR
)
1080 if(!kwsysProcessSetupSharedPipe(STD_ERROR_HANDLE
,
1081 &si
.StartupInfo
.hStdError
))
1083 kwsysProcessCleanup(cp
, 1);
1084 kwsysProcessCleanupHandleSafe(&si
.StartupInfo
.hStdError
,
1090 /* Replace the stderr pipe with the native pipe provided if any. In
1091 this case the pipe thread will still run but never report
1093 if(cp
->PipeNativeSTDERR
[1])
1095 if(!kwsysProcessSetupPipeNative(&si
.StartupInfo
.hStdError
,
1096 cp
->PipeNativeSTDERR
, 1))
1098 kwsysProcessCleanup(cp
, 1);
1099 kwsysProcessCleanupHandleSafe(&si
.StartupInfo
.hStdError
,
1105 /* Create the pipeline of processes. */
1108 for(i
=0; i
< cp
->NumberOfCommands
; ++i
)
1110 if(kwsysProcessCreate(cp
, i
, &si
, &readEnd
))
1112 cp
->ProcessEvents
[i
+1] = cp
->ProcessInformation
[i
].hProcess
;
1116 kwsysProcessCleanup(cp
, 1);
1118 /* Release resources that may have been allocated for this
1119 process before an error occurred. */
1120 kwsysProcessCleanupHandle(&readEnd
);
1121 kwsysProcessCleanupHandleSafe(&si
.StartupInfo
.hStdInput
,
1123 kwsysProcessCleanupHandleSafe(&si
.StartupInfo
.hStdOutput
,
1125 kwsysProcessCleanupHandleSafe(&si
.StartupInfo
.hStdError
,
1127 kwsysProcessCleanupHandle(&si
.ErrorPipeRead
);
1128 kwsysProcessCleanupHandle(&si
.ErrorPipeWrite
);
1133 /* Save a handle to the output pipe for the last process. */
1134 cp
->Pipe
[KWSYSPE_PIPE_STDOUT
].Read
= readEnd
;
1137 /* Close the inherited handles to the stderr pipe shared by all
1138 processes in the pipeline. The stdout and stdin pipes are not
1139 shared among all children and are therefore closed by
1140 kwsysProcessCreate after each child is created. */
1141 kwsysProcessCleanupHandleSafe(&si
.StartupInfo
.hStdError
, STD_ERROR_HANDLE
);
1143 /* Restore the working directory. */
1144 if(cp
->RealWorkingDirectory
)
1146 SetCurrentDirectory(cp
->RealWorkingDirectory
);
1147 free(cp
->RealWorkingDirectory
);
1148 cp
->RealWorkingDirectory
= 0;
1151 /* The timeout period starts now. */
1152 cp
->StartTime
= kwsysProcessTimeGetCurrent();
1153 cp
->TimeoutTime
= kwsysProcessTimeFromDouble(-1);
1155 /* All processes in the pipeline have been started in suspended
1156 mode. Resume them all now. */
1159 SetEvent(cp
->Win9xResumeEvent
);
1163 for(i
=0; i
< cp
->NumberOfCommands
; ++i
)
1165 ResumeThread(cp
->ProcessInformation
[i
].hThread
);
1169 /* ---- It is no longer safe to call kwsysProcessCleanup. ----- */
1170 /* Tell the pipe threads that a process has started. */
1171 for(i
=0; i
< KWSYSPE_PIPE_COUNT
; ++i
)
1173 ReleaseSemaphore(cp
->Pipe
[i
].Reader
.Ready
, 1, 0);
1174 ReleaseSemaphore(cp
->Pipe
[i
].Waker
.Ready
, 1, 0);
1177 /* We don't care about the children's main threads. */
1178 for(i
=0; i
< cp
->NumberOfCommands
; ++i
)
1180 kwsysProcessCleanupHandle(&cp
->ProcessInformation
[i
].hThread
);
1183 /* No pipe has reported data. */
1184 cp
->CurrentIndex
= KWSYSPE_PIPE_COUNT
;
1185 cp
->PipesLeft
= KWSYSPE_PIPE_COUNT
;
1187 /* The process has now started. */
1188 cp
->State
= kwsysProcess_State_Executing
;
1189 cp
->Detached
= cp
->OptionDetach
;
1192 /*--------------------------------------------------------------------------*/
1193 void kwsysProcess_Disown(kwsysProcess
* cp
)
1197 /* Make sure we are executing a detached process. */
1198 if(!cp
|| !cp
->Detached
|| cp
->State
!= kwsysProcess_State_Executing
||
1199 cp
->TimeoutExpired
|| cp
->Killed
|| cp
->Terminated
)
1204 /* Disable the reading threads. */
1205 kwsysProcessDisablePipeThreads(cp
);
1207 /* Wait for all pipe threads to reset. */
1208 for(i
=0; i
< KWSYSPE_PIPE_COUNT
; ++i
)
1210 WaitForSingleObject(cp
->Pipe
[i
].Reader
.Reset
, INFINITE
);
1211 WaitForSingleObject(cp
->Pipe
[i
].Waker
.Reset
, INFINITE
);
1214 /* We will not wait for exit, so cleanup now. */
1215 kwsysProcessCleanup(cp
, 0);
1217 /* The process has been disowned. */
1218 cp
->State
= kwsysProcess_State_Disowned
;
1221 /*--------------------------------------------------------------------------*/
1223 int kwsysProcess_WaitForData(kwsysProcess
* cp
, char** data
, int* length
,
1224 double* userTimeout
)
1226 kwsysProcessTime userStartTime
;
1227 kwsysProcessTime timeoutLength
;
1228 kwsysProcessTime timeoutTime
;
1233 int pipeId
= kwsysProcess_Pipe_None
;
1236 /* Make sure we are executing a process. */
1237 if(!cp
|| cp
->State
!= kwsysProcess_State_Executing
|| cp
->Killed
||
1240 return kwsysProcess_Pipe_None
;
1243 /* Record the time at which user timeout period starts. */
1244 userStartTime
= kwsysProcessTimeGetCurrent();
1246 /* Calculate the time at which a timeout will expire, and whether it
1247 is the user or process timeout. */
1248 user
= kwsysProcessGetTimeoutTime(cp
, userTimeout
, &timeoutTime
);
1250 /* Loop until we have a reason to return. */
1251 while(!done
&& cp
->PipesLeft
> 0)
1253 /* If we previously got data from a thread, let it know we are
1254 done with the data. */
1255 if(cp
->CurrentIndex
< KWSYSPE_PIPE_COUNT
)
1257 KWSYSPE_DEBUG((stderr
, "releasing reader %d\n", cp
->CurrentIndex
));
1258 ReleaseSemaphore(cp
->Pipe
[cp
->CurrentIndex
].Reader
.Go
, 1, 0);
1259 cp
->CurrentIndex
= KWSYSPE_PIPE_COUNT
;
1262 /* Setup a timeout if required. */
1263 if(kwsysProcessGetTimeoutLeft(&timeoutTime
, user
?userTimeout
:0,
1266 /* Timeout has already expired. */
1270 if(timeoutTime
.QuadPart
< 0)
1276 timeout
= kwsysProcessTimeToDWORD(timeoutLength
);
1279 /* Wait for a pipe's thread to signal or a process to terminate. */
1280 w
= WaitForMultipleObjects(cp
->ProcessEventsLength
, cp
->ProcessEvents
,
1282 if(w
== WAIT_TIMEOUT
)
1284 /* Timeout has expired. */
1288 else if(w
== WAIT_OBJECT_0
)
1290 /* Save the index of the reporting thread and release the mutex.
1291 The thread will block until we signal its Empty mutex. */
1292 cp
->CurrentIndex
= cp
->SharedIndex
;
1293 ReleaseSemaphore(cp
->SharedIndexMutex
, 1, 0);
1295 /* Data are available or a pipe closed. */
1296 if(cp
->Pipe
[cp
->CurrentIndex
].Closed
)
1298 /* The pipe closed at the write end. Close the read end and
1299 inform the wakeup thread it is done with this process. */
1300 kwsysProcessCleanupHandle(&cp
->Pipe
[cp
->CurrentIndex
].Read
);
1301 ReleaseSemaphore(cp
->Pipe
[cp
->CurrentIndex
].Waker
.Go
, 1, 0);
1302 KWSYSPE_DEBUG((stderr
, "wakeup %d\n", cp
->CurrentIndex
));
1305 else if(data
&& length
)
1307 /* Report this data. */
1308 *data
= cp
->Pipe
[cp
->CurrentIndex
].DataBuffer
;
1309 *length
= cp
->Pipe
[cp
->CurrentIndex
].DataLength
;
1310 switch(cp
->CurrentIndex
)
1312 case KWSYSPE_PIPE_STDOUT
:
1313 pipeId
= kwsysProcess_Pipe_STDOUT
; break;
1314 case KWSYSPE_PIPE_STDERR
:
1315 pipeId
= kwsysProcess_Pipe_STDERR
; break;
1322 /* A process has terminated. */
1323 kwsysProcessDestroy(cp
, w
-WAIT_OBJECT_0
);
1327 /* Update the user timeout. */
1330 kwsysProcessTime userEndTime
= kwsysProcessTimeGetCurrent();
1331 kwsysProcessTime difference
= kwsysProcessTimeSubtract(userEndTime
,
1333 double d
= kwsysProcessTimeToDouble(difference
);
1335 if(*userTimeout
< 0)
1341 /* Check what happened. */
1344 /* Data are ready on a pipe. */
1349 /* A timeout has expired. */
1352 /* The user timeout has expired. It has no time left. */
1353 return kwsysProcess_Pipe_Timeout
;
1357 /* The process timeout has expired. Kill the child now. */
1358 KWSYSPE_DEBUG((stderr
, "killing child because timeout expired\n"));
1359 kwsysProcess_Kill(cp
);
1360 cp
->TimeoutExpired
= 1;
1362 return kwsysProcess_Pipe_None
;
1367 /* The children have terminated and no more data are available. */
1368 return kwsysProcess_Pipe_None
;
1372 /*--------------------------------------------------------------------------*/
1373 int kwsysProcess_WaitForExit(kwsysProcess
* cp
, double* userTimeout
)
1378 /* Make sure we are executing a process. */
1379 if(!cp
|| cp
->State
!= kwsysProcess_State_Executing
)
1384 /* Wait for the process to terminate. Ignore all data. */
1385 while((pipe
= kwsysProcess_WaitForData(cp
, 0, 0, userTimeout
)) > 0)
1387 if(pipe
== kwsysProcess_Pipe_Timeout
)
1389 /* The user timeout has expired. */
1394 KWSYSPE_DEBUG((stderr
, "no more data\n"));
1396 /* When the last pipe closes in WaitForData, the loop terminates
1397 without releasing the pipe's thread. Release it now. */
1398 if(cp
->CurrentIndex
< KWSYSPE_PIPE_COUNT
)
1400 KWSYSPE_DEBUG((stderr
, "releasing reader %d\n", cp
->CurrentIndex
));
1401 ReleaseSemaphore(cp
->Pipe
[cp
->CurrentIndex
].Reader
.Go
, 1, 0);
1402 cp
->CurrentIndex
= KWSYSPE_PIPE_COUNT
;
1405 /* Wait for all pipe threads to reset. */
1406 for(i
=0; i
< KWSYSPE_PIPE_COUNT
; ++i
)
1408 KWSYSPE_DEBUG((stderr
, "waiting reader reset %d\n", i
));
1409 WaitForSingleObject(cp
->Pipe
[i
].Reader
.Reset
, INFINITE
);
1410 KWSYSPE_DEBUG((stderr
, "waiting waker reset %d\n", i
));
1411 WaitForSingleObject(cp
->Pipe
[i
].Waker
.Reset
, INFINITE
);
1414 /* ---- It is now safe again to call kwsysProcessCleanup. ----- */
1415 /* Close all the pipes. */
1416 kwsysProcessCleanup(cp
, 0);
1418 /* Determine the outcome. */
1421 /* We killed the child. */
1422 cp
->State
= kwsysProcess_State_Killed
;
1424 else if(cp
->TimeoutExpired
)
1426 /* The timeout expired. */
1427 cp
->State
= kwsysProcess_State_Expired
;
1431 /* The children exited. Report the outcome of the last process. */
1432 cp
->ExitCode
= cp
->CommandExitCodes
[cp
->NumberOfCommands
-1];
1433 if((cp
->ExitCode
& 0xF0000000) == 0xC0000000)
1435 /* Child terminated due to exceptional behavior. */
1436 cp
->State
= kwsysProcess_State_Exception
;
1438 kwsysProcessSetExitException(cp
, cp
->ExitCode
);
1442 /* Child exited without exception. */
1443 cp
->State
= kwsysProcess_State_Exited
;
1444 cp
->ExitException
= kwsysProcess_Exception_None
;
1445 cp
->ExitValue
= cp
->ExitCode
;
1452 /*--------------------------------------------------------------------------*/
1453 void kwsysProcess_Kill(kwsysProcess
* cp
)
1456 /* Make sure we are executing a process. */
1457 if(!cp
|| cp
->State
!= kwsysProcess_State_Executing
|| cp
->TimeoutExpired
||
1460 KWSYSPE_DEBUG((stderr
, "kill: child not executing\n"));
1464 /* Disable the reading threads. */
1465 KWSYSPE_DEBUG((stderr
, "kill: disabling pipe threads\n"));
1466 kwsysProcessDisablePipeThreads(cp
);
1468 /* Skip actually killing the child if it has already terminated. */
1471 KWSYSPE_DEBUG((stderr
, "kill: child already terminated\n"));
1475 /* Kill the children. */
1479 /* Windows 9x. Tell the forwarding executable to kill the child. */
1480 SetEvent(cp
->Win9xKillEvent
);
1484 /* Not Windows 9x. Just terminate the children. */
1485 for(i
=0; i
< cp
->NumberOfCommands
; ++i
)
1487 kwsysProcessKillTree(cp
->ProcessInformation
[i
].dwProcessId
);
1488 // close the handle if we kill it
1489 kwsysProcessCleanupHandle(&cp
->ProcessInformation
[i
].hThread
);
1490 kwsysProcessCleanupHandle(&cp
->ProcessInformation
[i
].hProcess
);
1494 /* We are killing the children and ignoring all data. Do not wait
1495 for them to exit. */
1498 /*--------------------------------------------------------------------------*/
1501 Function executed for each pipe's thread. Argument is a pointer to
1502 the kwsysProcessPipeData instance for this thread.
1504 DWORD WINAPI
kwsysProcessPipeThreadRead(LPVOID ptd
)
1506 kwsysProcessPipeData
* td
= (kwsysProcessPipeData
*)ptd
;
1507 kwsysProcess
* cp
= td
->Process
;
1509 /* Wait for a process to be ready. */
1510 while((WaitForSingleObject(td
->Reader
.Ready
, INFINITE
), !cp
->Deleting
))
1512 /* Read output from the process for this thread's pipe. */
1513 kwsysProcessPipeThreadReadPipe(cp
, td
);
1515 /* Signal the main thread we have reset for a new process. */
1516 ReleaseSemaphore(td
->Reader
.Reset
, 1, 0);
1521 /*--------------------------------------------------------------------------*/
1524 Function called in each pipe's thread to handle data for one
1525 execution of a subprocess.
1527 void kwsysProcessPipeThreadReadPipe(kwsysProcess
* cp
, kwsysProcessPipeData
* td
)
1529 /* Wait for space in the thread's buffer. */
1530 while((KWSYSPE_DEBUG((stderr
, "wait for read %d\n", td
->Index
)),
1531 WaitForSingleObject(td
->Reader
.Go
, INFINITE
), !td
->Closed
))
1533 KWSYSPE_DEBUG((stderr
, "reading %d\n", td
->Index
));
1535 /* Read data from the pipe. This may block until data are available. */
1536 if(!ReadFile(td
->Read
, td
->DataBuffer
, KWSYSPE_PIPE_BUFFER_SIZE
,
1537 &td
->DataLength
, 0))
1539 if(GetLastError() != ERROR_BROKEN_PIPE
)
1541 /* UNEXPECTED failure to read the pipe. */
1544 /* The pipe closed. There are no more data to read. */
1546 KWSYSPE_DEBUG((stderr
, "read closed %d\n", td
->Index
));
1549 KWSYSPE_DEBUG((stderr
, "read %d\n", td
->Index
));
1551 /* Wait for our turn to be handled by the main thread. */
1552 WaitForSingleObject(cp
->SharedIndexMutex
, INFINITE
);
1554 KWSYSPE_DEBUG((stderr
, "reporting read %d\n", td
->Index
));
1556 /* Tell the main thread we have something to report. */
1557 cp
->SharedIndex
= td
->Index
;
1558 ReleaseSemaphore(cp
->Full
, 1, 0);
1561 /* We were signalled to exit with our buffer empty. Reset the
1562 mutex for a new process. */
1563 KWSYSPE_DEBUG((stderr
, "self releasing reader %d\n", td
->Index
));
1564 ReleaseSemaphore(td
->Reader
.Go
, 1, 0);
1567 /*--------------------------------------------------------------------------*/
1570 Function executed for each pipe's thread. Argument is a pointer to
1571 the kwsysProcessPipeData instance for this thread.
1573 DWORD WINAPI
kwsysProcessPipeThreadWake(LPVOID ptd
)
1575 kwsysProcessPipeData
* td
= (kwsysProcessPipeData
*)ptd
;
1576 kwsysProcess
* cp
= td
->Process
;
1578 /* Wait for a process to be ready. */
1579 while((WaitForSingleObject(td
->Waker
.Ready
, INFINITE
), !cp
->Deleting
))
1581 /* Wait for a possible wakeup. */
1582 kwsysProcessPipeThreadWakePipe(cp
, td
);
1584 /* Signal the main thread we have reset for a new process. */
1585 ReleaseSemaphore(td
->Waker
.Reset
, 1, 0);
1590 /*--------------------------------------------------------------------------*/
1593 Function called in each pipe's thread to handle reading thread
1594 wakeup for one execution of a subprocess.
1596 void kwsysProcessPipeThreadWakePipe(kwsysProcess
* cp
, kwsysProcessPipeData
* td
)
1600 /* Wait for a possible wake command. */
1601 KWSYSPE_DEBUG((stderr
, "wait for wake %d\n", td
->Index
));
1602 WaitForSingleObject(td
->Waker
.Go
, INFINITE
);
1603 KWSYSPE_DEBUG((stderr
, "waking %d\n", td
->Index
));
1605 /* If the pipe is not closed, we need to wake up the reading thread. */
1609 KWSYSPE_DEBUG((stderr
, "waker %d writing byte\n", td
->Index
));
1610 WriteFile(td
->Write
, "", 1, &dummy
, 0);
1611 KWSYSPE_DEBUG((stderr
, "waker %d wrote byte\n", td
->Index
));
1615 /*--------------------------------------------------------------------------*/
1616 /* Initialize a process control structure for kwsysProcess_Execute. */
1617 int kwsysProcessInitialize(kwsysProcess
* cp
)
1619 /* Reset internal status flags. */
1620 cp
->TimeoutExpired
= 0;
1623 cp
->ExitException
= kwsysProcess_Exception_None
;
1627 /* Reset error data. */
1628 cp
->ErrorMessage
[0] = 0;
1629 strcpy(cp
->ExitExceptionString
, "No exception");
1631 /* Allocate process information for each process. */
1632 cp
->ProcessInformation
=
1633 (PROCESS_INFORMATION
*)malloc(sizeof(PROCESS_INFORMATION
) *
1634 cp
->NumberOfCommands
);
1635 if(!cp
->ProcessInformation
)
1639 ZeroMemory(cp
->ProcessInformation
,
1640 sizeof(PROCESS_INFORMATION
) * cp
->NumberOfCommands
);
1641 if(cp
->CommandExitCodes
)
1643 free(cp
->CommandExitCodes
);
1645 cp
->CommandExitCodes
= (DWORD
*)malloc(sizeof(DWORD
)*cp
->NumberOfCommands
);
1646 if(!cp
->CommandExitCodes
)
1650 ZeroMemory(cp
->CommandExitCodes
, sizeof(DWORD
)*cp
->NumberOfCommands
);
1652 /* Allocate event wait array. The first event is cp->Full, the rest
1653 are the process termination events. */
1654 cp
->ProcessEvents
= (PHANDLE
)malloc(sizeof(HANDLE
)*(cp
->NumberOfCommands
+1));
1655 if(!cp
->ProcessEvents
)
1659 ZeroMemory(cp
->ProcessEvents
, sizeof(HANDLE
) * (cp
->NumberOfCommands
+1));
1660 cp
->ProcessEvents
[0] = cp
->Full
;
1661 cp
->ProcessEventsLength
= cp
->NumberOfCommands
+1;
1663 /* Allocate space to save the real working directory of this process. */
1664 if(cp
->WorkingDirectory
)
1666 cp
->RealWorkingDirectoryLength
= GetCurrentDirectory(0, 0);
1667 if(cp
->RealWorkingDirectoryLength
> 0)
1669 cp
->RealWorkingDirectory
= malloc(cp
->RealWorkingDirectoryLength
);
1670 if(!cp
->RealWorkingDirectory
)
1680 /*--------------------------------------------------------------------------*/
1681 int kwsysProcessCreate(kwsysProcess
* cp
, int index
,
1682 kwsysProcessCreateInformation
* si
,
1685 /* Setup the process's stdin. */
1688 /* Create an inherited duplicate of the read end from the output
1689 pipe of the previous process. This also closes the
1690 non-inherited version. */
1691 if(!DuplicateHandle(GetCurrentProcess(), *readEnd
,
1692 GetCurrentProcess(), readEnd
,
1693 0, TRUE
, (DUPLICATE_CLOSE_SOURCE
|
1694 DUPLICATE_SAME_ACCESS
)))
1698 si
->StartupInfo
.hStdInput
= *readEnd
;
1700 /* This function is done with this handle. */
1703 else if(cp
->PipeFileSTDIN
)
1705 /* Create a handle to read a file for stdin. */
1706 HANDLE fin
= CreateFile(cp
->PipeFileSTDIN
, GENERIC_READ
|GENERIC_WRITE
,
1707 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1708 0, OPEN_EXISTING
, 0, 0);
1709 if(fin
== INVALID_HANDLE_VALUE
)
1713 /* Create an inherited duplicate of the handle. This also closes
1714 the non-inherited version. */
1715 if(!DuplicateHandle(GetCurrentProcess(), fin
,
1716 GetCurrentProcess(), &fin
,
1717 0, TRUE
, (DUPLICATE_CLOSE_SOURCE
|
1718 DUPLICATE_SAME_ACCESS
)))
1722 si
->StartupInfo
.hStdInput
= fin
;
1724 else if(cp
->PipeSharedSTDIN
)
1726 /* Share this process's stdin with the child. */
1727 if(!kwsysProcessSetupSharedPipe(STD_INPUT_HANDLE
,
1728 &si
->StartupInfo
.hStdInput
))
1733 else if(cp
->PipeNativeSTDIN
[0])
1735 /* Use the provided native pipe. */
1736 if(!kwsysProcessSetupPipeNative(&si
->StartupInfo
.hStdInput
,
1737 cp
->PipeNativeSTDIN
, 0))
1744 /* Explicitly give the child no stdin. */
1745 si
->StartupInfo
.hStdInput
= INVALID_HANDLE_VALUE
;
1748 /* Setup the process's stdout. */
1750 DWORD maybeClose
= DUPLICATE_CLOSE_SOURCE
;
1753 /* Create the output pipe for this process. Neither end is directly
1755 if(!CreatePipe(readEnd
, &writeEnd
, 0, 0))
1760 /* Create an inherited duplicate of the write end. Close the
1761 non-inherited version unless this is the last process. Save the
1762 non-inherited write end of the last process. */
1763 if(index
== cp
->NumberOfCommands
-1)
1765 cp
->Pipe
[KWSYSPE_PIPE_STDOUT
].Write
= writeEnd
;
1768 if(!DuplicateHandle(GetCurrentProcess(), writeEnd
,
1769 GetCurrentProcess(), &writeEnd
,
1770 0, TRUE
, (maybeClose
| DUPLICATE_SAME_ACCESS
)))
1774 si
->StartupInfo
.hStdOutput
= writeEnd
;
1777 /* Replace the stdout pipe with a file if requested. In this case
1778 the pipe thread will still run but never report data. */
1779 if(index
== cp
->NumberOfCommands
-1 && cp
->PipeFileSTDOUT
)
1781 if(!kwsysProcessSetupOutputPipeFile(&si
->StartupInfo
.hStdOutput
,
1782 cp
->PipeFileSTDOUT
))
1788 /* Replace the stdout pipe of the last child with the parent
1789 process's if requested. In this case the pipe thread will still
1790 run but never report data. */
1791 if(index
== cp
->NumberOfCommands
-1 && cp
->PipeSharedSTDOUT
)
1793 if(!kwsysProcessSetupSharedPipe(STD_OUTPUT_HANDLE
,
1794 &si
->StartupInfo
.hStdOutput
))
1800 /* Replace the stdout pipe with the native pipe provided if any. In
1801 this case the pipe thread will still run but never report
1803 if(index
== cp
->NumberOfCommands
-1 && cp
->PipeNativeSTDOUT
[1])
1805 if(!kwsysProcessSetupPipeNative(&si
->StartupInfo
.hStdOutput
,
1806 cp
->PipeNativeSTDOUT
, 1))
1812 /* Create the child process. */
1818 /* Create an error reporting pipe for the forwarding executable.
1819 Neither end is directly inherited. */
1820 if(!CreatePipe(&si
->ErrorPipeRead
, &si
->ErrorPipeWrite
, 0, 0))
1825 /* Create an inherited duplicate of the write end. This also closes
1826 the non-inherited version. */
1827 if(!DuplicateHandle(GetCurrentProcess(), si
->ErrorPipeWrite
,
1828 GetCurrentProcess(), &si
->ErrorPipeWrite
,
1829 0, TRUE
, (DUPLICATE_CLOSE_SOURCE
|
1830 DUPLICATE_SAME_ACCESS
)))
1835 /* The forwarding executable is given a handle to the error pipe
1836 and resume and kill events. */
1837 realCommand
= malloc(strlen(cp
->Win9x
)+strlen(cp
->Commands
[index
])+100);
1842 sprintf(realCommand
, "%s %p %p %p %d %s", cp
->Win9x
,
1843 si
->ErrorPipeWrite
, cp
->Win9xResumeEvent
, cp
->Win9xKillEvent
,
1844 cp
->HideWindow
, cp
->Commands
[index
]);
1848 realCommand
= cp
->Commands
[index
];
1851 /* Create the child in a suspended state so we can wait until all
1852 children have been created before running any one. */
1853 r
= CreateProcess(0, realCommand
, 0, 0, TRUE
,
1854 cp
->Win9x
? 0 : CREATE_SUSPENDED
, 0, 0,
1855 &si
->StartupInfo
, &cp
->ProcessInformation
[index
]);
1861 /* Close the error pipe write end so we can detect when the
1862 forwarding executable closes it. */
1863 kwsysProcessCleanupHandle(&si
->ErrorPipeWrite
);
1866 /* Wait for the forwarding executable to report an error or
1867 close the error pipe to report success. */
1870 while(total
< KWSYSPE_PIPE_BUFFER_SIZE
&& n
> 0)
1872 if(ReadFile(si
->ErrorPipeRead
, cp
->ErrorMessage
+total
,
1873 KWSYSPE_PIPE_BUFFER_SIZE
-total
, &n
, 0))
1882 if(total
> 0 || GetLastError() != ERROR_BROKEN_PIPE
)
1884 /* The forwarding executable could not run the process, or
1885 there was an error reading from its error pipe. Preserve
1886 the last error while cleaning up the forwarding executable
1887 so the cleanup our caller does reports the proper error. */
1888 DWORD error
= GetLastError();
1889 kwsysProcessCleanupHandle(&cp
->ProcessInformation
[index
].hThread
);
1890 kwsysProcessCleanupHandle(&cp
->ProcessInformation
[index
].hProcess
);
1891 SetLastError(error
);
1895 kwsysProcessCleanupHandle(&si
->ErrorPipeRead
);
1904 /* Successfully created this child process. Close the current
1905 process's copies of the inherited stdout and stdin handles. The
1906 stderr handle is shared among all children and is closed by
1907 kwsysProcess_Execute after all children have been created. */
1908 kwsysProcessCleanupHandleSafe(&si
->StartupInfo
.hStdInput
,
1910 kwsysProcessCleanupHandleSafe(&si
->StartupInfo
.hStdOutput
,
1916 /*--------------------------------------------------------------------------*/
1917 void kwsysProcessDestroy(kwsysProcess
* cp
, int event
)
1922 /* Find the process index for the termination event. */
1923 for(index
=0; index
< cp
->NumberOfCommands
; ++index
)
1925 if(cp
->ProcessInformation
[index
].hProcess
== cp
->ProcessEvents
[event
])
1931 /* Check the exit code of the process. */
1932 GetExitCodeProcess(cp
->ProcessInformation
[index
].hProcess
,
1933 &cp
->CommandExitCodes
[index
]);
1935 /* Close the process handle for the terminated process. */
1936 kwsysProcessCleanupHandle(&cp
->ProcessInformation
[index
].hProcess
);
1938 /* Remove the process from the available events. */
1939 cp
->ProcessEventsLength
-= 1;
1940 for(i
=event
; i
< cp
->ProcessEventsLength
; ++i
)
1942 cp
->ProcessEvents
[i
] = cp
->ProcessEvents
[i
+1];
1945 /* Check if all processes have terminated. */
1946 if(cp
->ProcessEventsLength
== 1)
1950 /* Close our copies of the pipe write handles so the pipe threads
1951 can detect end-of-data. */
1952 for(i
=0; i
< KWSYSPE_PIPE_COUNT
; ++i
)
1954 /* TODO: If the child created its own child (our grandchild)
1955 which inherited a copy of the pipe write-end then the pipe
1956 may not close and we will still need the waker write pipe.
1957 However we still want to be able to detect end-of-data in the
1958 normal case. The reader thread will have to switch to using
1959 PeekNamedPipe to read the last bit of data from the pipe
1960 without blocking. This is equivalent to using a non-blocking
1962 KWSYSPE_DEBUG((stderr
, "closing wakeup write %d\n", i
));
1963 kwsysProcessCleanupHandle(&cp
->Pipe
[i
].Write
);
1968 /*--------------------------------------------------------------------------*/
1969 int kwsysProcessSetupOutputPipeFile(PHANDLE phandle
, const char* name
)
1977 /* Close the existing inherited handle. */
1978 kwsysProcessCleanupHandle(phandle
);
1980 /* Create a handle to write a file for the pipe. */
1981 fout
= CreateFile(name
, GENERIC_WRITE
, FILE_SHARE_READ
, 0,
1982 CREATE_ALWAYS
, 0, 0);
1983 if(fout
== INVALID_HANDLE_VALUE
)
1988 /* Create an inherited duplicate of the handle. This also closes
1989 the non-inherited version. */
1990 if(!DuplicateHandle(GetCurrentProcess(), fout
,
1991 GetCurrentProcess(), &fout
,
1992 0, TRUE
, (DUPLICATE_CLOSE_SOURCE
|
1993 DUPLICATE_SAME_ACCESS
)))
1998 /* Assign the replacement handle. */
2003 /*--------------------------------------------------------------------------*/
2004 int kwsysProcessSetupSharedPipe(DWORD nStdHandle
, PHANDLE handle
)
2006 /* Check whether the handle to be shared is already inherited. */
2009 if(GetHandleInformation(GetStdHandle(nStdHandle
), &flags
) &&
2010 (flags
& HANDLE_FLAG_INHERIT
))
2015 /* Cleanup the previous handle. */
2016 kwsysProcessCleanupHandle(handle
);
2018 /* If the standard handle is not inherited then duplicate it to
2019 create an inherited copy. Do not close the original handle when
2023 *handle
= GetStdHandle(nStdHandle
);
2026 else if(DuplicateHandle(GetCurrentProcess(), GetStdHandle(nStdHandle
),
2027 GetCurrentProcess(), handle
,
2028 0, TRUE
, DUPLICATE_SAME_ACCESS
))
2034 /* The given standard handle is not valid for this process. Some
2035 child processes may break if they do not have a valid standard
2036 pipe, so give the child an empty pipe. For the stdin pipe we
2037 want to close the write end and give the read end to the child.
2038 For stdout and stderr we want to close the read end and give
2039 the write end to the child. */
2040 int child_end
= (nStdHandle
== STD_INPUT_HANDLE
)? 0:1;
2041 int parent_end
= (nStdHandle
== STD_INPUT_HANDLE
)? 1:0;
2042 HANDLE emptyPipe
[2];
2043 if(!CreatePipe(&emptyPipe
[0], &emptyPipe
[1], 0, 0))
2048 /* Close the non-inherited end so the pipe will be broken
2050 CloseHandle(emptyPipe
[parent_end
]);
2052 /* Create an inherited duplicate of the handle. This also
2053 closes the non-inherited version. */
2054 if(!DuplicateHandle(GetCurrentProcess(), emptyPipe
[child_end
],
2055 GetCurrentProcess(), &emptyPipe
[child_end
],
2056 0, TRUE
, (DUPLICATE_CLOSE_SOURCE
|
2057 DUPLICATE_SAME_ACCESS
)))
2062 /* Give the inherited handle to the child. */
2063 *handle
= emptyPipe
[child_end
];
2068 /*--------------------------------------------------------------------------*/
2069 int kwsysProcessSetupPipeNative(PHANDLE handle
, HANDLE p
[2], int isWrite
)
2071 /* Close the existing inherited handle. */
2072 kwsysProcessCleanupHandle(handle
);
2074 /* Create an inherited duplicate of the handle. This also closes
2075 the non-inherited version. */
2076 if(!DuplicateHandle(GetCurrentProcess(), p
[isWrite
? 1:0],
2077 GetCurrentProcess(), handle
,
2078 0, TRUE
, (DUPLICATE_CLOSE_SOURCE
|
2079 DUPLICATE_SAME_ACCESS
)))
2087 /*--------------------------------------------------------------------------*/
2089 /* Close the given handle if it is open. Reset its value to 0. */
2090 void kwsysProcessCleanupHandle(PHANDLE h
)
2099 /*--------------------------------------------------------------------------*/
2101 /* Close the given handle if it is open and not a standard handle.
2102 Reset its value to 0. */
2103 void kwsysProcessCleanupHandleSafe(PHANDLE h
, DWORD nStdHandle
)
2105 if(h
&& *h
&& (*h
!= GetStdHandle(nStdHandle
)))
2112 /*--------------------------------------------------------------------------*/
2114 /* Close all handles created by kwsysProcess_Execute. */
2115 void kwsysProcessCleanup(kwsysProcess
* cp
, int error
)
2118 /* If this is an error case, report the error. */
2121 /* Construct an error message if one has not been provided already. */
2122 if(cp
->ErrorMessage
[0] == 0)
2124 /* Format the error message. */
2125 DWORD original
= GetLastError();
2126 DWORD length
= FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
|
2127 FORMAT_MESSAGE_IGNORE_INSERTS
, 0, original
,
2128 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
2129 cp
->ErrorMessage
, KWSYSPE_PIPE_BUFFER_SIZE
, 0);
2132 /* FormatMessage failed. Use a default message. */
2133 _snprintf(cp
->ErrorMessage
, KWSYSPE_PIPE_BUFFER_SIZE
,
2134 "Process execution failed with error 0x%X. "
2135 "FormatMessage failed with error 0x%X",
2136 original
, GetLastError());
2140 /* Remove trailing period and newline, if any. */
2141 kwsysProcessCleanErrorMessage(cp
);
2143 /* Set the error state. */
2144 cp
->State
= kwsysProcess_State_Error
;
2146 /* Cleanup any processes already started in a suspended state. */
2147 if(cp
->ProcessInformation
)
2151 SetEvent(cp
->Win9xKillEvent
);
2155 for(i
=0; i
< cp
->NumberOfCommands
; ++i
)
2157 if(cp
->ProcessInformation
[i
].hProcess
)
2159 TerminateProcess(cp
->ProcessInformation
[i
].hProcess
, 255);
2160 WaitForSingleObject(cp
->ProcessInformation
[i
].hProcess
, INFINITE
);
2164 for(i
=0; i
< cp
->NumberOfCommands
; ++i
)
2166 kwsysProcessCleanupHandle(&cp
->ProcessInformation
[i
].hThread
);
2167 kwsysProcessCleanupHandle(&cp
->ProcessInformation
[i
].hProcess
);
2171 /* Restore the working directory. */
2172 if(cp
->RealWorkingDirectory
)
2174 SetCurrentDirectory(cp
->RealWorkingDirectory
);
2179 if(cp
->ProcessInformation
)
2181 free(cp
->ProcessInformation
);
2182 cp
->ProcessInformation
= 0;
2184 if(cp
->ProcessEvents
)
2186 free(cp
->ProcessEvents
);
2187 cp
->ProcessEvents
= 0;
2189 if(cp
->RealWorkingDirectory
)
2191 free(cp
->RealWorkingDirectory
);
2192 cp
->RealWorkingDirectory
= 0;
2195 /* Close each pipe. */
2196 for(i
=0; i
< KWSYSPE_PIPE_COUNT
; ++i
)
2198 kwsysProcessCleanupHandle(&cp
->Pipe
[i
].Write
);
2199 kwsysProcessCleanupHandle(&cp
->Pipe
[i
].Read
);
2200 cp
->Pipe
[i
].Closed
= 0;
2204 /*--------------------------------------------------------------------------*/
2205 void kwsysProcessCleanErrorMessage(kwsysProcess
* cp
)
2207 /* Remove trailing period and newline, if any. */
2208 size_t length
= strlen(cp
->ErrorMessage
);
2209 if(cp
->ErrorMessage
[length
-1] == '\n')
2211 cp
->ErrorMessage
[length
-1] = 0;
2213 if(length
> 0 && cp
->ErrorMessage
[length
-1] == '\r')
2215 cp
->ErrorMessage
[length
-1] = 0;
2219 if(length
> 0 && cp
->ErrorMessage
[length
-1] == '.')
2221 cp
->ErrorMessage
[length
-1] = 0;
2225 /*--------------------------------------------------------------------------*/
2226 int kwsysProcessComputeCommandLength(kwsysProcess
* cp
,
2227 char const* const* command
)
2232 /* Treat the first argument as a verbatim command line. Use its
2233 length directly and add space for the null-terminator. */
2234 length
= (int)strlen(*command
)+1;
2238 /* Compute the length of the command line when it is converted to
2239 a single string. Space for the null-terminator is allocated by
2240 the whitespace character allocated for the first argument that
2241 will not be used. */
2242 char const* const* arg
;
2243 for(arg
= command
; *arg
; ++arg
)
2245 /* Add the length of this argument. It already includes room
2246 for a separating space or terminating null. */
2247 length
+= kwsysSystem_Shell_GetArgumentSizeForWindows(*arg
, 0);
2254 /*--------------------------------------------------------------------------*/
2255 void kwsysProcessComputeCommandLine(kwsysProcess
* cp
,
2256 char const* const* command
,
2261 /* Copy the verbatim command line into the buffer. */
2262 strcpy(cmd
, *command
);
2266 /* Construct the command line in the allocated buffer. */
2267 char const* const* arg
;
2268 for(arg
= command
; *arg
; ++arg
)
2270 /* Add the separating space if this is not the first argument. */
2276 /* Add the current argument. */
2277 cmd
= kwsysSystem_Shell_GetArgumentForWindows(*arg
, cmd
, 0);
2280 /* Add the terminating null character to the command line. */
2285 /*--------------------------------------------------------------------------*/
2286 /* Get the time at which either the process or user timeout will
2287 expire. Returns 1 if the user timeout is first, and 0 otherwise. */
2288 int kwsysProcessGetTimeoutTime(kwsysProcess
* cp
, double* userTimeout
,
2289 kwsysProcessTime
* timeoutTime
)
2291 /* The first time this is called, we need to calculate the time at
2292 which the child will timeout. */
2293 if(cp
->Timeout
&& cp
->TimeoutTime
.QuadPart
< 0)
2295 kwsysProcessTime length
= kwsysProcessTimeFromDouble(cp
->Timeout
);
2296 cp
->TimeoutTime
= kwsysProcessTimeAdd(cp
->StartTime
, length
);
2299 /* Start with process timeout. */
2300 *timeoutTime
= cp
->TimeoutTime
;
2302 /* Check if the user timeout is earlier. */
2305 kwsysProcessTime currentTime
= kwsysProcessTimeGetCurrent();
2306 kwsysProcessTime userTimeoutLength
= kwsysProcessTimeFromDouble(*userTimeout
);
2307 kwsysProcessTime userTimeoutTime
= kwsysProcessTimeAdd(currentTime
,
2309 if(timeoutTime
->QuadPart
< 0 ||
2310 kwsysProcessTimeLess(userTimeoutTime
, *timeoutTime
))
2312 *timeoutTime
= userTimeoutTime
;
2319 /*--------------------------------------------------------------------------*/
2320 /* Get the length of time before the given timeout time arrives.
2321 Returns 1 if the time has already arrived, and 0 otherwise. */
2322 int kwsysProcessGetTimeoutLeft(kwsysProcessTime
* timeoutTime
,
2323 double* userTimeout
,
2324 kwsysProcessTime
* timeoutLength
)
2326 if(timeoutTime
->QuadPart
< 0)
2328 /* No timeout time has been requested. */
2333 /* Calculate the remaining time. */
2334 kwsysProcessTime currentTime
= kwsysProcessTimeGetCurrent();
2335 *timeoutLength
= kwsysProcessTimeSubtract(*timeoutTime
, currentTime
);
2337 if(timeoutLength
->QuadPart
< 0 && userTimeout
&& *userTimeout
<= 0)
2339 /* Caller has explicitly requested a zero timeout. */
2340 timeoutLength
->QuadPart
= 0;
2343 if(timeoutLength
->QuadPart
< 0)
2345 /* Timeout has already expired. */
2350 /* There is some time left. */
2356 /*--------------------------------------------------------------------------*/
2357 kwsysProcessTime
kwsysProcessTimeGetCurrent()
2359 kwsysProcessTime current
;
2361 GetSystemTimeAsFileTime(&ft
);
2362 current
.LowPart
= ft
.dwLowDateTime
;
2363 current
.HighPart
= ft
.dwHighDateTime
;
2367 /*--------------------------------------------------------------------------*/
2368 DWORD
kwsysProcessTimeToDWORD(kwsysProcessTime t
)
2370 return (DWORD
)(t
.QuadPart
* 0.0001);
2373 /*--------------------------------------------------------------------------*/
2374 double kwsysProcessTimeToDouble(kwsysProcessTime t
)
2376 return t
.QuadPart
* 0.0000001;
2379 /*--------------------------------------------------------------------------*/
2380 kwsysProcessTime
kwsysProcessTimeFromDouble(double d
)
2383 t
.QuadPart
= (LONGLONG
)(d
*10000000);
2387 /*--------------------------------------------------------------------------*/
2388 int kwsysProcessTimeLess(kwsysProcessTime in1
, kwsysProcessTime in2
)
2390 return in1
.QuadPart
< in2
.QuadPart
;
2393 /*--------------------------------------------------------------------------*/
2394 kwsysProcessTime
kwsysProcessTimeAdd(kwsysProcessTime in1
, kwsysProcessTime in2
)
2396 kwsysProcessTime out
;
2397 out
.QuadPart
= in1
.QuadPart
+ in2
.QuadPart
;
2401 /*--------------------------------------------------------------------------*/
2402 kwsysProcessTime
kwsysProcessTimeSubtract(kwsysProcessTime in1
, kwsysProcessTime in2
)
2404 kwsysProcessTime out
;
2405 out
.QuadPart
= in1
.QuadPart
- in2
.QuadPart
;
2409 /*--------------------------------------------------------------------------*/
2410 #define KWSYSPE_CASE(type, str) \
2411 cp->ExitException = kwsysProcess_Exception_##type; \
2412 strcpy(cp->ExitExceptionString, str)
2413 static void kwsysProcessSetExitException(kwsysProcess
* cp
, int code
)
2417 case STATUS_CONTROL_C_EXIT
:
2418 KWSYSPE_CASE(Interrupt
, "User interrupt"); break;
2420 case STATUS_FLOAT_DENORMAL_OPERAND
:
2421 KWSYSPE_CASE(Numerical
, "Floating-point exception (denormal operand)"); break;
2422 case STATUS_FLOAT_DIVIDE_BY_ZERO
:
2423 KWSYSPE_CASE(Numerical
, "Divide-by-zero"); break;
2424 case STATUS_FLOAT_INEXACT_RESULT
:
2425 KWSYSPE_CASE(Numerical
, "Floating-point exception (inexact result)"); break;
2426 case STATUS_FLOAT_INVALID_OPERATION
:
2427 KWSYSPE_CASE(Numerical
, "Invalid floating-point operation"); break;
2428 case STATUS_FLOAT_OVERFLOW
:
2429 KWSYSPE_CASE(Numerical
, "Floating-point overflow"); break;
2430 case STATUS_FLOAT_STACK_CHECK
:
2431 KWSYSPE_CASE(Numerical
, "Floating-point stack check failed"); break;
2432 case STATUS_FLOAT_UNDERFLOW
:
2433 KWSYSPE_CASE(Numerical
, "Floating-point underflow"); break;
2434 #ifdef STATUS_FLOAT_MULTIPLE_FAULTS
2435 case STATUS_FLOAT_MULTIPLE_FAULTS
:
2436 KWSYSPE_CASE(Numerical
, "Floating-point exception (multiple faults)"); break;
2438 #ifdef STATUS_FLOAT_MULTIPLE_TRAPS
2439 case STATUS_FLOAT_MULTIPLE_TRAPS
:
2440 KWSYSPE_CASE(Numerical
, "Floating-point exception (multiple traps)"); break;
2442 case STATUS_INTEGER_DIVIDE_BY_ZERO
:
2443 KWSYSPE_CASE(Numerical
, "Integer divide-by-zero"); break;
2444 case STATUS_INTEGER_OVERFLOW
:
2445 KWSYSPE_CASE(Numerical
, "Integer overflow"); break;
2447 case STATUS_DATATYPE_MISALIGNMENT
:
2448 KWSYSPE_CASE(Fault
, "Datatype misalignment"); break;
2449 case STATUS_ACCESS_VIOLATION
:
2450 KWSYSPE_CASE(Fault
, "Access violation"); break;
2451 case STATUS_IN_PAGE_ERROR
:
2452 KWSYSPE_CASE(Fault
, "In-page error"); break;
2453 case STATUS_INVALID_HANDLE
:
2454 KWSYSPE_CASE(Fault
, "Invalid hanlde"); break;
2455 case STATUS_NONCONTINUABLE_EXCEPTION
:
2456 KWSYSPE_CASE(Fault
, "Noncontinuable exception"); break;
2457 case STATUS_INVALID_DISPOSITION
:
2458 KWSYSPE_CASE(Fault
, "Invalid disposition"); break;
2459 case STATUS_ARRAY_BOUNDS_EXCEEDED
:
2460 KWSYSPE_CASE(Fault
, "Array bounds exceeded"); break;
2461 case STATUS_STACK_OVERFLOW
:
2462 KWSYSPE_CASE(Fault
, "Stack overflow"); break;
2464 case STATUS_ILLEGAL_INSTRUCTION
:
2465 KWSYSPE_CASE(Illegal
, "Illegal instruction"); break;
2466 case STATUS_PRIVILEGED_INSTRUCTION
:
2467 KWSYSPE_CASE(Illegal
, "Privileged instruction"); break;
2469 case STATUS_NO_MEMORY
:
2471 cp
->ExitException
= kwsysProcess_Exception_Other
;
2472 sprintf(cp
->ExitExceptionString
, "Exit code 0x%x\n", code
);
2478 typedef struct kwsysProcess_List_s kwsysProcess_List
;
2479 static kwsysProcess_List
* kwsysProcess_List_New(void);
2480 static void kwsysProcess_List_Delete(kwsysProcess_List
* self
);
2481 static int kwsysProcess_List_Update(kwsysProcess_List
* self
);
2482 static int kwsysProcess_List_NextProcess(kwsysProcess_List
* self
);
2483 static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List
* self
);
2484 static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List
* self
);
2486 /*--------------------------------------------------------------------------*/
2487 /* Windows NT 4 API definitions. */
2488 #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
2489 typedef LONG NTSTATUS
;
2490 typedef LONG KPRIORITY
;
2491 typedef struct _UNICODE_STRING UNICODE_STRING
;
2492 struct _UNICODE_STRING
2495 USHORT MaximumLength
;
2499 /* The process information structure. Declare only enough to get
2500 process identifiers. The rest may be ignored because we use the
2501 NextEntryDelta to move through an array of instances. */
2502 typedef struct _SYSTEM_PROCESS_INFORMATION SYSTEM_PROCESS_INFORMATION
;
2503 typedef SYSTEM_PROCESS_INFORMATION
* PSYSTEM_PROCESS_INFORMATION
;
2504 struct _SYSTEM_PROCESS_INFORMATION
2506 ULONG NextEntryDelta
;
2509 LARGE_INTEGER CreateTime
;
2510 LARGE_INTEGER UserTime
;
2511 LARGE_INTEGER KernelTime
;
2512 UNICODE_STRING ProcessName
;
2513 KPRIORITY BasePriority
;
2515 ULONG InheritedFromProcessId
;
2518 /*--------------------------------------------------------------------------*/
2519 /* Toolhelp32 API definitions. */
2520 #define TH32CS_SNAPPROCESS 0x00000002
2521 typedef struct tagPROCESSENTRY32 PROCESSENTRY32
;
2522 typedef PROCESSENTRY32
* LPPROCESSENTRY32
;
2523 struct tagPROCESSENTRY32
2527 DWORD th32ProcessID
;
2528 DWORD th32DefaultHeapID
;
2531 DWORD th32ParentProcessID
;
2532 LONG pcPriClassBase
;
2534 char szExeFile
[MAX_PATH
];
2537 /*--------------------------------------------------------------------------*/
2538 /* Windows API function types. */
2539 typedef HANDLE (WINAPI
* CreateToolhelp32SnapshotType
)(DWORD
, DWORD
);
2540 typedef BOOL (WINAPI
* Process32FirstType
)(HANDLE
, LPPROCESSENTRY32
);
2541 typedef BOOL (WINAPI
* Process32NextType
)(HANDLE
, LPPROCESSENTRY32
);
2542 typedef NTSTATUS (WINAPI
* ZwQuerySystemInformationType
)(ULONG
, PVOID
,
2546 /*--------------------------------------------------------------------------*/
2547 static int kwsysProcess_List__New_NT4(kwsysProcess_List
* self
);
2548 static int kwsysProcess_List__New_Snapshot(kwsysProcess_List
* self
);
2549 static void kwsysProcess_List__Delete_NT4(kwsysProcess_List
* self
);
2550 static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List
* self
);
2551 static int kwsysProcess_List__Update_NT4(kwsysProcess_List
* self
);
2552 static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List
* self
);
2553 static int kwsysProcess_List__Next_NT4(kwsysProcess_List
* self
);
2554 static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List
* self
);
2555 static int kwsysProcess_List__GetProcessId_NT4(kwsysProcess_List
* self
);
2556 static int kwsysProcess_List__GetProcessId_Snapshot(kwsysProcess_List
* self
);
2557 static int kwsysProcess_List__GetParentId_NT4(kwsysProcess_List
* self
);
2558 static int kwsysProcess_List__GetParentId_Snapshot(kwsysProcess_List
* self
);
2560 struct kwsysProcess_List_s
2562 /* Implementation switches at runtime based on version of Windows. */
2565 /* Implementation functions and data for NT 4. */
2566 ZwQuerySystemInformationType P_ZwQuerySystemInformation
;
2569 PSYSTEM_PROCESS_INFORMATION CurrentInfo
;
2571 /* Implementation functions and data for other Windows versions. */
2572 CreateToolhelp32SnapshotType P_CreateToolhelp32Snapshot
;
2573 Process32FirstType P_Process32First
;
2574 Process32NextType P_Process32Next
;
2576 PROCESSENTRY32 CurrentEntry
;
2579 /*--------------------------------------------------------------------------*/
2580 static kwsysProcess_List
* kwsysProcess_List_New(void)
2583 kwsysProcess_List
* self
;
2585 /* Allocate and initialize the list object. */
2586 if(!(self
= (kwsysProcess_List
*)malloc(sizeof(kwsysProcess_List
))))
2590 memset(self
, 0, sizeof(*self
));
2592 /* Select an implementation. */
2593 ZeroMemory(&osv
, sizeof(osv
));
2594 osv
.dwOSVersionInfoSize
= sizeof(osv
);
2596 self
->NT4
= (osv
.dwPlatformId
== VER_PLATFORM_WIN32_NT
&&
2597 osv
.dwMajorVersion
< 5)? 1:0;
2599 /* Initialize the selected implementation. */
2601 kwsysProcess_List__New_NT4(self
) :
2602 kwsysProcess_List__New_Snapshot(self
)))
2604 kwsysProcess_List_Delete(self
);
2608 /* Update to the current set of processes. */
2609 if(!kwsysProcess_List_Update(self
))
2611 kwsysProcess_List_Delete(self
);
2617 /*--------------------------------------------------------------------------*/
2618 static void kwsysProcess_List_Delete(kwsysProcess_List
* self
)
2624 kwsysProcess_List__Delete_NT4(self
);
2628 kwsysProcess_List__Delete_Snapshot(self
);
2634 /*--------------------------------------------------------------------------*/
2635 static int kwsysProcess_List_Update(kwsysProcess_List
* self
)
2637 return self
? (self
->NT4
?
2638 kwsysProcess_List__Update_NT4(self
) :
2639 kwsysProcess_List__Update_Snapshot(self
)) : 0;
2642 /*--------------------------------------------------------------------------*/
2643 static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List
* self
)
2645 return self
? (self
->NT4
?
2646 kwsysProcess_List__GetProcessId_NT4(self
) :
2647 kwsysProcess_List__GetProcessId_Snapshot(self
)) : -1;
2651 /*--------------------------------------------------------------------------*/
2652 static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List
* self
)
2654 return self
? (self
->NT4
?
2655 kwsysProcess_List__GetParentId_NT4(self
) :
2656 kwsysProcess_List__GetParentId_Snapshot(self
)) : -1;
2660 /*--------------------------------------------------------------------------*/
2661 static int kwsysProcess_List_NextProcess(kwsysProcess_List
* self
)
2663 return (self
? (self
->NT4
?
2664 kwsysProcess_List__Next_NT4(self
) :
2665 kwsysProcess_List__Next_Snapshot(self
)) : 0);
2668 /*--------------------------------------------------------------------------*/
2669 static int kwsysProcess_List__New_NT4(kwsysProcess_List
* self
)
2671 /* Get a handle to the NT runtime module that should already be
2672 loaded in this program. This does not actually increment the
2673 reference count to the module so we do not need to close the
2675 HANDLE hNT
= GetModuleHandle("ntdll.dll");
2678 /* Get pointers to the needed API functions. */
2679 self
->P_ZwQuerySystemInformation
=
2680 ((ZwQuerySystemInformationType
)
2681 GetProcAddress(hNT
, "ZwQuerySystemInformation"));
2683 if(!self
->P_ZwQuerySystemInformation
)
2688 /* Allocate an initial process information buffer. */
2689 self
->BufferSize
= 32768;
2690 self
->Buffer
= (char*)malloc(self
->BufferSize
);
2691 return self
->Buffer
? 1:0;
2694 /*--------------------------------------------------------------------------*/
2695 static void kwsysProcess_List__Delete_NT4(kwsysProcess_List
* self
)
2697 /* Free the process information buffer. */
2704 /*--------------------------------------------------------------------------*/
2705 static int kwsysProcess_List__Update_NT4(kwsysProcess_List
* self
)
2707 self
->CurrentInfo
= 0;
2710 /* Query number 5 is for system process list. */
2712 self
->P_ZwQuerySystemInformation(5, self
->Buffer
, self
->BufferSize
, 0);
2713 if(status
== STATUS_INFO_LENGTH_MISMATCH
)
2715 /* The query requires a bigger buffer. */
2716 int newBufferSize
= self
->BufferSize
* 2;
2717 char* newBuffer
= (char*)malloc(newBufferSize
);
2721 self
->Buffer
= newBuffer
;
2722 self
->BufferSize
= newBufferSize
;
2729 else if(status
>= 0)
2731 /* The query succeeded. Initialize traversal of the process list. */
2732 self
->CurrentInfo
= (PSYSTEM_PROCESS_INFORMATION
)self
->Buffer
;
2737 /* The query failed. */
2743 /*--------------------------------------------------------------------------*/
2744 static int kwsysProcess_List__Next_NT4(kwsysProcess_List
* self
)
2746 if(self
->CurrentInfo
)
2748 if(self
->CurrentInfo
->NextEntryDelta
> 0)
2750 self
->CurrentInfo
= ((PSYSTEM_PROCESS_INFORMATION
)
2751 ((char*)self
->CurrentInfo
+
2752 self
->CurrentInfo
->NextEntryDelta
));
2755 self
->CurrentInfo
= 0;
2760 /*--------------------------------------------------------------------------*/
2761 static int kwsysProcess_List__GetProcessId_NT4(kwsysProcess_List
* self
)
2763 return self
->CurrentInfo
? self
->CurrentInfo
->ProcessId
: -1;
2766 /*--------------------------------------------------------------------------*/
2767 static int kwsysProcess_List__GetParentId_NT4(kwsysProcess_List
* self
)
2769 return self
->CurrentInfo
? self
->CurrentInfo
->InheritedFromProcessId
: -1;
2772 /*--------------------------------------------------------------------------*/
2773 static int kwsysProcess_List__New_Snapshot(kwsysProcess_List
* self
)
2775 /* Get a handle to the Windows runtime module that should already be
2776 loaded in this program. This does not actually increment the
2777 reference count to the module so we do not need to close the
2779 HANDLE hKernel
= GetModuleHandle("kernel32.dll");
2782 self
->P_CreateToolhelp32Snapshot
=
2783 ((CreateToolhelp32SnapshotType
)
2784 GetProcAddress(hKernel
, "CreateToolhelp32Snapshot"));
2785 self
->P_Process32First
=
2786 ((Process32FirstType
)
2787 GetProcAddress(hKernel
, "Process32First"));
2788 self
->P_Process32Next
=
2789 ((Process32NextType
)
2790 GetProcAddress(hKernel
, "Process32Next"));
2792 return (self
->P_CreateToolhelp32Snapshot
&&
2793 self
->P_Process32First
&&
2794 self
->P_Process32Next
)? 1:0;
2797 /*--------------------------------------------------------------------------*/
2798 static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List
* self
)
2802 CloseHandle(self
->Snapshot
);
2806 /*--------------------------------------------------------------------------*/
2807 static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List
* self
)
2811 CloseHandle(self
->Snapshot
);
2813 if(!(self
->Snapshot
=
2814 self
->P_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0)))
2818 ZeroMemory(&self
->CurrentEntry
, sizeof(self
->CurrentEntry
));
2819 self
->CurrentEntry
.dwSize
= sizeof(self
->CurrentEntry
);
2820 if(!self
->P_Process32First(self
->Snapshot
, &self
->CurrentEntry
))
2822 CloseHandle(self
->Snapshot
);
2829 /*--------------------------------------------------------------------------*/
2830 static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List
* self
)
2834 if(self
->P_Process32Next(self
->Snapshot
, &self
->CurrentEntry
))
2838 CloseHandle(self
->Snapshot
);
2844 /*--------------------------------------------------------------------------*/
2845 static int kwsysProcess_List__GetProcessId_Snapshot(kwsysProcess_List
* self
)
2847 return self
->Snapshot
? self
->CurrentEntry
.th32ProcessID
: -1;
2850 /*--------------------------------------------------------------------------*/
2851 static int kwsysProcess_List__GetParentId_Snapshot(kwsysProcess_List
* self
)
2853 return self
->Snapshot
? self
->CurrentEntry
.th32ParentProcessID
: -1;
2856 /*--------------------------------------------------------------------------*/
2857 static void kwsysProcessKill(DWORD pid
)
2859 HANDLE h
= OpenProcess(PROCESS_TERMINATE
, 0, pid
);
2862 TerminateProcess(h
, 255);
2863 WaitForSingleObject(h
, INFINITE
);
2868 /*--------------------------------------------------------------------------*/
2869 static void kwsysProcessKillTree(int pid
)
2871 kwsysProcess_List
* plist
= kwsysProcess_List_New();
2872 kwsysProcessKill(pid
);
2877 if(kwsysProcess_List_GetCurrentParentId(plist
) == pid
)
2879 int ppid
= kwsysProcess_List_GetCurrentProcessId(plist
);
2880 kwsysProcessKillTree(ppid
);
2882 } while(kwsysProcess_List_NextProcess(plist
));
2883 kwsysProcess_List_Delete(plist
);
2887 /*--------------------------------------------------------------------------*/
2888 static void kwsysProcessDisablePipeThreads(kwsysProcess
* cp
)
2892 /* If data were just reported data, release the pipe's thread. */
2893 if(cp
->CurrentIndex
< KWSYSPE_PIPE_COUNT
)
2895 KWSYSPE_DEBUG((stderr
, "releasing reader %d\n", cp
->CurrentIndex
));
2896 ReleaseSemaphore(cp
->Pipe
[cp
->CurrentIndex
].Reader
.Go
, 1, 0);
2897 cp
->CurrentIndex
= KWSYSPE_PIPE_COUNT
;
2900 /* Wakeup all reading threads that are not on closed pipes. */
2901 for(i
=0; i
< KWSYSPE_PIPE_COUNT
; ++i
)
2903 /* The wakeup threads will write one byte to the pipe write ends.
2904 If there are no data in the pipe then this is enough to wakeup
2905 the reading threads. If there are already data in the pipe
2906 this may block. We cannot use PeekNamedPipe to check whether
2907 there are data because an outside process might still be
2908 writing data if we are disowning it. Also, PeekNamedPipe will
2909 block if checking a pipe on which the reading thread is
2910 currently calling ReadPipe. Therefore we need a separate
2911 thread to call WriteFile. If it blocks, that is okay because
2912 it will unblock when we close the read end and break the pipe
2914 if(cp
->Pipe
[i
].Read
)
2916 KWSYSPE_DEBUG((stderr
, "releasing waker %d\n", i
));
2917 ReleaseSemaphore(cp
->Pipe
[i
].Waker
.Go
, 1, 0);
2921 /* Tell pipe threads to reset until we run another process. */
2922 while(cp
->PipesLeft
> 0)
2924 /* The waking threads will cause all reading threads to report.
2925 Wait for the next one and save its index. */
2926 KWSYSPE_DEBUG((stderr
, "waiting for reader\n"));
2927 WaitForSingleObject(cp
->Full
, INFINITE
);
2928 cp
->CurrentIndex
= cp
->SharedIndex
;
2929 ReleaseSemaphore(cp
->SharedIndexMutex
, 1, 0);
2930 KWSYSPE_DEBUG((stderr
, "got reader %d\n", cp
->CurrentIndex
));
2932 /* We are done reading this pipe. Close its read handle. */
2933 cp
->Pipe
[cp
->CurrentIndex
].Closed
= 1;
2934 kwsysProcessCleanupHandle(&cp
->Pipe
[cp
->CurrentIndex
].Read
);
2937 /* Tell the reading thread we are done with the data. It will
2938 reset immediately because the pipe is closed. */
2939 ReleaseSemaphore(cp
->Pipe
[cp
->CurrentIndex
].Reader
.Go
, 1, 0);