Initial commit.
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / kwsys / ProcessWin32.c
blob7bd0e83b2f4e25c5caa879315406c0a58102d54f
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. */
20 #if 0
21 # include "Process.h.in"
22 # include "System.h.in"
23 #endif
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
39 Q190351 and Q150956.
43 #ifdef _MSC_VER
44 #pragma warning (push, 1)
45 #endif
46 #include <windows.h> /* Windows API */
47 #include <string.h> /* strlen, strdup */
48 #include <stdio.h> /* sprintf */
49 #include <io.h> /* _unlink */
50 #ifdef __WATCOMC__
51 #define _unlink unlink
52 #endif
54 #ifndef _MAX_FNAME
55 #define _MAX_FNAME 4096
56 #endif
57 #ifndef _MAX_PATH
58 #define _MAX_PATH 4096
59 #endif
61 #ifdef _MSC_VER
62 #pragma warning (pop)
63 #pragma warning (disable: 4514)
64 #pragma warning (disable: 4706)
65 #endif
67 #if defined(__BORLANDC__)
68 # pragma warn -8004 /* assigned a value that is never used */
69 # pragma warn -8060 /* Assignment inside if() condition. */
70 #endif
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. */
81 #if 0
82 # define KWSYSPE_DEBUG(x) \
83 ( \
84 (void*)cp == (void*)0x00226DE0? \
85 ( \
86 fprintf(stderr, "%d/%p/%d ", (int)GetCurrentProcessId(), cp, __LINE__), \
87 fprintf x, \
88 fflush(stderr), \
89 1 \
90 ) : (1) \
92 #else
93 # define KWSYSPE_DEBUG(x) (void)1
94 #endif
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,
121 PHANDLE readEnd);
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],
126 int isWrite);
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,
135 char* cmd);
136 static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
137 kwsysProcessTime* timeoutTime);
138 static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
139 double* userTimeout,
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. */
159 HANDLE Thread;
161 /* Semaphore indicating to the thread that a process has started. */
162 HANDLE Ready;
164 /* Semaphore indicating to the thread that it should begin work. */
165 HANDLE Go;
167 /* Semaphore indicating thread has reset for another process. */
168 HANDLE Reset;
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. */
184 int Index;
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. */
195 DWORD DataLength;
197 /* Whether the pipe has been closed. */
198 int Closed;
200 /* Handle for the read end of this pipe. */
201 HANDLE Read;
203 /* Handle for the write end of this pipe. */
204 HANDLE Write;
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. */
214 int State;
216 /* The command lines to execute. */
217 char** Commands;
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. */
227 int OptionDetach;
229 /* Whether the child was created as a detached process. */
230 int Detached;
232 /* Whether to hide the child process's window. */
233 int HideWindow;
235 /* Whether to treat command lines as verbatim. */
236 int Verbatim;
238 /* On Win9x platforms, the path to the forwarding executable. */
239 char* Win9x;
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. */
251 HANDLE Full;
253 /* Whether we are currently deleting this kwsysProcess instance. */
254 int Deleting;
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. */
260 char* PipeFileSTDIN;
261 char* PipeFileSTDOUT;
262 char* PipeFileSTDERR;
264 /* Whether each pipe is shared with the parent process. */
265 int PipeSharedSTDIN;
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. */
275 HANDLE Win9xHandle;
277 /* ------------- Data managed per call to Execute ------------- */
279 /* The exceptional behavior that terminated the process, if any. */
280 int ExitException;
282 /* The process exit code. */
283 DWORD ExitCode;
285 /* The process return code, if any. */
286 int ExitValue;
288 /* Index of last pipe to report data, if any. */
289 int CurrentIndex;
291 /* Index shared by threads to report data. */
292 int SharedIndex;
294 /* The timeout length. */
295 double Timeout;
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. */
304 int Killed;
306 /* Flag for whether the timeout expired. */
307 int TimeoutExpired;
309 /* Flag for whether the process has terminated. */
310 int Terminated;
312 /* The number of pipes still open during execution and while waiting
313 for pipes to close after process termination. */
314 int PipesLeft;
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)
337 int i;
339 /* Process control structure. */
340 kwsysProcess* cp;
342 /* Path to Win9x forwarding executable. */
343 char* win9x = 0;
345 /* Windows version number data. */
346 OSVERSIONINFO osv;
348 /* Allocate a process control structure. */
349 cp = (kwsysProcess*)malloc(sizeof(kwsysProcess));
350 if(!cp)
352 /* Could not allocate memory for the control structure. */
353 return 0;
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
364 windows. */
365 ZeroMemory(&osv, sizeof(osv));
366 osv.dwOSVersionInfoSize = sizeof(osv);
367 GetVersionEx(&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
377 slash. */
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_%u_%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);
391 if(!win9x)
393 kwsysProcess_Delete(cp);
394 return 0;
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
402 write it. */
403 if(win9x)
405 if(!kwsysEncodedWriteArrayProcessFwd9x(win9x))
407 /* Failed to create forwarding executable. Give up. */
408 free(win9x);
409 kwsysProcess_Delete(cp);
410 return 0;
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. */
420 _unlink(win9x);
421 free(win9x);
422 kwsysProcess_Delete(cp);
423 return 0;
426 else
428 /* Failed to find a place to put forwarding executable. */
429 kwsysProcess_Delete(cp);
430 return 0;
434 /* Save the path to the forwarding executable. */
435 cp->Win9x = win9x;
437 /* Initially no thread owns the mutex. Initialize semaphore to 1. */
438 if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0)))
440 kwsysProcess_Delete(cp);
441 return 0;
444 /* Initially no data are available. Initialize semaphore to 0. */
445 if(!(cp->Full = CreateSemaphore(0, 0, 1, 0)))
447 kwsysProcess_Delete(cp);
448 return 0;
451 if(cp->Win9x)
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
459 child. */
460 if(!(cp->Win9xResumeEvent = CreateEvent(&sa, TRUE, 0, 0)))
462 kwsysProcess_Delete(cp);
463 return 0;
466 /* Create an event to tell the forwarding executable to kill the
467 child. */
468 if(!(cp->Win9xKillEvent = CreateEvent(&sa, TRUE, 0, 0)))
470 kwsysProcess_Delete(cp);
471 return 0;
475 /* Create the thread to read each pipe. */
476 for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
478 DWORD dummy=0;
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);
490 return 0;
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);
497 return 0;
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);
504 return 0;
507 /* Create the reading thread. It will block immediately. The
508 thread will not make deeply nested calls, so we need only a
509 small stack. */
510 if(!(cp->Pipe[i].Reader.Thread = CreateThread(0, 1024,
511 kwsysProcessPipeThreadRead,
512 &cp->Pipe[i], 0, &dummy)))
514 kwsysProcess_Delete(cp);
515 return 0;
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);
522 return 0;
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);
529 return 0;
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);
536 return 0;
539 /* Create the waking thread. It will block immediately. The
540 thread will not make deeply nested calls, so we need only a
541 small stack. */
542 if(!(cp->Pipe[i].Waker.Thread = CreateThread(0, 1024,
543 kwsysProcessPipeThreadWake,
544 &cp->Pipe[i], 0, &dummy)))
546 kwsysProcess_Delete(cp);
547 return 0;
551 return cp;
554 /*--------------------------------------------------------------------------*/
555 void kwsysProcess_Delete(kwsysProcess* cp)
557 int i;
559 /* Make sure we have an instance. */
560 if(!cp)
562 return;
565 /* If the process is executing, wait for it to finish. */
566 if(cp->State == kwsysProcess_State_Executing)
568 if(cp->Detached)
570 kwsysProcess_Disown(cp);
572 else
574 kwsysProcess_WaitForExit(cp, 0);
578 /* We are deleting the kwsysProcess instance. */
579 cp->Deleting = 1;
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. */
626 if(cp->Win9x)
628 kwsysProcessCleanupHandle(&cp->Win9xResumeEvent);
629 kwsysProcessCleanupHandle(&cp->Win9xKillEvent);
632 /* Free memory. */
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);
642 if(cp->Win9x)
644 /* Close our handle to the forwarding executable file. This will
645 cause it to be deleted. */
646 kwsysProcessCleanupHandle(&cp->Win9xHandle);
648 free(cp);
651 /*--------------------------------------------------------------------------*/
652 int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
654 int i;
655 if(!cp)
657 return 0;
659 for(i=0; i < cp->NumberOfCommands; ++i)
661 free(cp->Commands[i]);
663 cp->NumberOfCommands = 0;
664 if(cp->Commands)
666 free(cp->Commands);
667 cp->Commands = 0;
669 if(command)
671 return kwsysProcess_AddCommand(cp, command);
673 return 1;
676 /*--------------------------------------------------------------------------*/
677 int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
679 int newNumberOfCommands;
680 char** newCommands;
682 /* Make sure we have a command to add. */
683 if(!cp || !command || !*command)
685 return 0;
688 /* Allocate a new array for command pointers. */
689 newNumberOfCommands = cp->NumberOfCommands + 1;
690 if(!(newCommands = (char**)malloc(sizeof(char*) * newNumberOfCommands)))
692 /* Out of memory. */
693 return 0;
696 /* Copy any existing commands into the new array. */
698 int i;
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
711 argument. */
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])
722 /* Out of memory. */
723 free(newCommands);
724 return 0;
727 /* Construct the command line in the allocated buffer. */
728 kwsysProcessComputeCommandLine(cp, command,
729 newCommands[cp->NumberOfCommands]);
732 /* Save the new array of commands. */
733 free(cp->Commands);
734 cp->Commands = newCommands;
735 cp->NumberOfCommands = newNumberOfCommands;
736 return 1;
739 /*--------------------------------------------------------------------------*/
740 void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
742 if(!cp)
744 return;
746 cp->Timeout = timeout;
747 if(cp->Timeout < 0)
749 cp->Timeout = 0;
753 /*--------------------------------------------------------------------------*/
754 int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
756 if(!cp)
758 return 0;
760 if(cp->WorkingDirectory)
762 free(cp->WorkingDirectory);
763 cp->WorkingDirectory = 0;
765 if(dir && dir[0])
767 /* We must convert the working directory to a full path. */
768 DWORD length = GetFullPathName(dir, 0, 0, 0);
769 if(length > 0)
771 cp->WorkingDirectory = (char*)malloc(length);
772 if(!cp->WorkingDirectory)
774 return 0;
776 if(!GetFullPathName(dir, length, cp->WorkingDirectory, 0))
778 free(cp->WorkingDirectory);
779 cp->WorkingDirectory = 0;
780 return 0;
784 return 1;
787 /*--------------------------------------------------------------------------*/
788 int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
790 char** pfile;
791 if(!cp)
793 return 0;
795 switch(pipe)
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;
800 default: return 0;
802 if(*pfile)
804 free(*pfile);
805 *pfile = 0;
807 if(file)
809 *pfile = malloc(strlen(file)+1);
810 if(!*pfile)
812 return 0;
814 strcpy(*pfile, file);
817 /* If we are redirecting the pipe, do not share it or use a native
818 pipe. */
819 if(*pfile)
821 kwsysProcess_SetPipeNative(cp, pipe, 0);
822 kwsysProcess_SetPipeShared(cp, pipe, 0);
825 return 1;
828 /*--------------------------------------------------------------------------*/
829 void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared)
831 if(!cp)
833 return;
836 switch(pipe)
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;
841 default: return;
844 /* If we are sharing the pipe, do not redirect it to a file or use a
845 native pipe. */
846 if(shared)
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;
858 if(!cp)
860 return;
863 switch(pipe)
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;
868 default: return;
871 /* Copy the native pipe handles provided. */
872 if(p)
874 pPipeNative[0] = p[0];
875 pPipeNative[1] = p[1];
877 else
879 pPipeNative[0] = 0;
880 pPipeNative[1] = 0;
883 /* If we are using a native pipe, do not share it or redirect it to
884 a file. */
885 if(p)
887 kwsysProcess_SetPipeFile(cp, pipe, 0);
888 kwsysProcess_SetPipeShared(cp, pipe, 0);
892 /*--------------------------------------------------------------------------*/
893 int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
895 if(!cp)
897 return 0;
900 switch(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;
905 default: return 0;
909 /*--------------------------------------------------------------------------*/
910 void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
912 if(!cp)
914 return;
917 switch(optionId)
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;
922 default: 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)
953 if(!cp)
955 return "Process management structure could not be allocated";
957 else if(cp->State == kwsysProcess_State_Error)
959 return cp->ErrorMessage;
961 return "Success";
964 /*--------------------------------------------------------------------------*/
965 const char* kwsysProcess_GetExceptionString(kwsysProcess* cp)
967 if(!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)
981 int i;
983 /* Child startup control data. */
984 kwsysProcessCreateInformation si;
986 /* Do not execute a second time. */
987 if(!cp || cp->State == kwsysProcess_State_Executing)
989 return;
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;
997 return;
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);
1009 return;
1011 SetCurrentDirectory(cp->WorkingDirectory);
1014 /* Reset the Win9x resume and kill events. */
1015 if(cp->Win9x)
1017 if(!ResetEvent(cp->Win9xResumeEvent))
1019 kwsysProcessCleanup(cp, 1);
1020 return;
1022 if(!ResetEvent(cp->Win9xKillEvent))
1024 kwsysProcessCleanup(cp, 1);
1025 return;
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);
1047 return;
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);
1059 return;
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);
1071 return;
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
1077 data. */
1078 if(cp->PipeSharedSTDERR)
1080 if(!kwsysProcessSetupSharedPipe(STD_ERROR_HANDLE,
1081 &si.StartupInfo.hStdError))
1083 kwsysProcessCleanup(cp, 1);
1084 kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
1085 STD_ERROR_HANDLE);
1086 return;
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
1092 data. */
1093 if(cp->PipeNativeSTDERR[1])
1095 if(!kwsysProcessSetupPipeNative(&si.StartupInfo.hStdError,
1096 cp->PipeNativeSTDERR, 1))
1098 kwsysProcessCleanup(cp, 1);
1099 kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
1100 STD_ERROR_HANDLE);
1101 return;
1105 /* Create the pipeline of processes. */
1107 HANDLE readEnd = 0;
1108 for(i=0; i < cp->NumberOfCommands; ++i)
1110 if(kwsysProcessCreate(cp, i, &si, &readEnd))
1112 cp->ProcessEvents[i+1] = cp->ProcessInformation[i].hProcess;
1114 else
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,
1122 STD_INPUT_HANDLE);
1123 kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdOutput,
1124 STD_OUTPUT_HANDLE);
1125 kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
1126 STD_ERROR_HANDLE);
1127 kwsysProcessCleanupHandle(&si.ErrorPipeRead);
1128 kwsysProcessCleanupHandle(&si.ErrorPipeWrite);
1129 return;
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. */
1157 if(cp->Win9x)
1159 SetEvent(cp->Win9xResumeEvent);
1161 else
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)
1195 int i;
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)
1201 return;
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;
1229 DWORD timeout;
1230 int user;
1231 int done = 0;
1232 int expired = 0;
1233 int pipeId = kwsysProcess_Pipe_None;
1234 DWORD w;
1236 /* Make sure we are executing a process. */
1237 if(!cp || cp->State != kwsysProcess_State_Executing || cp->Killed ||
1238 cp->TimeoutExpired)
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,
1264 &timeoutLength))
1266 /* Timeout has already expired. */
1267 expired = 1;
1268 break;
1270 if(timeoutTime.QuadPart < 0)
1272 timeout = INFINITE;
1274 else
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,
1281 0, timeout);
1282 if(w == WAIT_TIMEOUT)
1284 /* Timeout has expired. */
1285 expired = 1;
1286 done = 1;
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));
1303 --cp->PipesLeft;
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;
1317 done = 1;
1320 else
1322 /* A process has terminated. */
1323 kwsysProcessDestroy(cp, w-WAIT_OBJECT_0);
1327 /* Update the user timeout. */
1328 if(userTimeout)
1330 kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent();
1331 kwsysProcessTime difference = kwsysProcessTimeSubtract(userEndTime,
1332 userStartTime);
1333 double d = kwsysProcessTimeToDouble(difference);
1334 *userTimeout -= d;
1335 if(*userTimeout < 0)
1337 *userTimeout = 0;
1341 /* Check what happened. */
1342 if(pipeId)
1344 /* Data are ready on a pipe. */
1345 return pipeId;
1347 else if(expired)
1349 /* A timeout has expired. */
1350 if(user)
1352 /* The user timeout has expired. It has no time left. */
1353 return kwsysProcess_Pipe_Timeout;
1355 else
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;
1361 cp->Killed = 0;
1362 return kwsysProcess_Pipe_None;
1365 else
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)
1375 int i;
1376 int pipe;
1378 /* Make sure we are executing a process. */
1379 if(!cp || cp->State != kwsysProcess_State_Executing)
1381 return 1;
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. */
1390 return 0;
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. */
1419 if(cp->Killed)
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;
1429 else
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;
1437 cp->ExitValue = 1;
1438 kwsysProcessSetExitException(cp, cp->ExitCode);
1440 else
1442 /* Child exited without exception. */
1443 cp->State = kwsysProcess_State_Exited;
1444 cp->ExitException = kwsysProcess_Exception_None;
1445 cp->ExitValue = cp->ExitCode;
1449 return 1;
1452 /*--------------------------------------------------------------------------*/
1453 void kwsysProcess_Kill(kwsysProcess* cp)
1455 int i;
1456 /* Make sure we are executing a process. */
1457 if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired ||
1458 cp->Killed)
1460 KWSYSPE_DEBUG((stderr, "kill: child not executing\n"));
1461 return;
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. */
1469 if(cp->Terminated)
1471 KWSYSPE_DEBUG((stderr, "kill: child already terminated\n"));
1472 return;
1475 /* Kill the children. */
1476 cp->Killed = 1;
1477 if(cp->Win9x)
1479 /* Windows 9x. Tell the forwarding executable to kill the child. */
1480 SetEvent(cp->Win9xKillEvent);
1482 else
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);
1518 return 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. */
1545 td->Closed = 1;
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);
1587 return 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)
1598 (void)cp;
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. */
1606 if(!td->Closed)
1608 DWORD dummy;
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;
1621 cp->Terminated = 0;
1622 cp->Killed = 0;
1623 cp->ExitException = kwsysProcess_Exception_None;
1624 cp->ExitCode = 1;
1625 cp->ExitValue = 1;
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)
1637 return 0;
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)
1648 return 0;
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)
1657 return 0;
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)
1672 return 0;
1677 return 1;
1680 /*--------------------------------------------------------------------------*/
1681 int kwsysProcessCreate(kwsysProcess* cp, int index,
1682 kwsysProcessCreateInformation* si,
1683 PHANDLE readEnd)
1685 /* Setup the process's stdin. */
1686 if(*readEnd)
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)))
1696 return 0;
1698 si->StartupInfo.hStdInput = *readEnd;
1700 /* This function is done with this handle. */
1701 *readEnd = 0;
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)
1711 return 0;
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)))
1720 return 0;
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))
1730 return 0;
1733 else if(cp->PipeNativeSTDIN[0])
1735 /* Use the provided native pipe. */
1736 if(!kwsysProcessSetupPipeNative(&si->StartupInfo.hStdInput,
1737 cp->PipeNativeSTDIN, 0))
1739 return 0;
1742 else
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;
1751 HANDLE writeEnd;
1753 /* Create the output pipe for this process. Neither end is directly
1754 inherited. */
1755 if(!CreatePipe(readEnd, &writeEnd, 0, 0))
1757 return 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;
1766 maybeClose = 0;
1768 if(!DuplicateHandle(GetCurrentProcess(), writeEnd,
1769 GetCurrentProcess(), &writeEnd,
1770 0, TRUE, (maybeClose | DUPLICATE_SAME_ACCESS)))
1772 return 0;
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))
1784 return 0;
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))
1796 return 0;
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
1802 data. */
1803 if(index == cp->NumberOfCommands-1 && cp->PipeNativeSTDOUT[1])
1805 if(!kwsysProcessSetupPipeNative(&si->StartupInfo.hStdOutput,
1806 cp->PipeNativeSTDOUT, 1))
1808 return 0;
1812 /* Create the child process. */
1814 BOOL r;
1815 char* realCommand;
1816 if(cp->Win9x)
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))
1822 return 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)))
1832 return 0;
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);
1838 if(!realCommand)
1840 return 0;
1842 sprintf(realCommand, "%s %p %p %p %d %s", cp->Win9x,
1843 si->ErrorPipeWrite, cp->Win9xResumeEvent, cp->Win9xKillEvent,
1844 cp->HideWindow, cp->Commands[index]);
1846 else
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]);
1856 if(cp->Win9x)
1858 /* Free memory. */
1859 free(realCommand);
1861 /* Close the error pipe write end so we can detect when the
1862 forwarding executable closes it. */
1863 kwsysProcessCleanupHandle(&si->ErrorPipeWrite);
1864 if(r)
1866 /* Wait for the forwarding executable to report an error or
1867 close the error pipe to report success. */
1868 DWORD total = 0;
1869 DWORD n = 1;
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))
1875 total += n;
1877 else
1879 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);
1892 return 0;
1895 kwsysProcessCleanupHandle(&si->ErrorPipeRead);
1898 if(!r)
1900 return 0;
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,
1909 STD_INPUT_HANDLE);
1910 kwsysProcessCleanupHandleSafe(&si->StartupInfo.hStdOutput,
1911 STD_OUTPUT_HANDLE);
1913 return 1;
1916 /*--------------------------------------------------------------------------*/
1917 void kwsysProcessDestroy(kwsysProcess* cp, int event)
1919 int i;
1920 int index;
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])
1927 break;
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)
1948 cp->Terminated = 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
1961 read on posix. */
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)
1971 HANDLE fout;
1972 if(!name)
1974 return 1;
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)
1985 return 0;
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)))
1995 return 0;
1998 /* Assign the replacement handle. */
1999 *phandle = fout;
2000 return 1;
2003 /*--------------------------------------------------------------------------*/
2004 int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle)
2006 /* Check whether the handle to be shared is already inherited. */
2007 DWORD flags;
2008 int inherited = 0;
2009 if(GetHandleInformation(GetStdHandle(nStdHandle), &flags) &&
2010 (flags & HANDLE_FLAG_INHERIT))
2012 inherited = 1;
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
2020 duplicating! */
2021 if(inherited)
2023 *handle = GetStdHandle(nStdHandle);
2024 return 1;
2026 else if(DuplicateHandle(GetCurrentProcess(), GetStdHandle(nStdHandle),
2027 GetCurrentProcess(), handle,
2028 0, TRUE, DUPLICATE_SAME_ACCESS))
2030 return 1;
2032 else
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))
2045 return 0;
2048 /* Close the non-inherited end so the pipe will be broken
2049 immediately. */
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)))
2059 return 0;
2062 /* Give the inherited handle to the child. */
2063 *handle = emptyPipe[child_end];
2064 return 1;
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)))
2081 return 0;
2084 return 1;
2087 /*--------------------------------------------------------------------------*/
2089 /* Close the given handle if it is open. Reset its value to 0. */
2090 void kwsysProcessCleanupHandle(PHANDLE h)
2092 if(h && *h)
2094 CloseHandle(*h);
2095 *h = 0;
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)))
2107 CloseHandle(*h);
2108 *h = 0;
2112 /*--------------------------------------------------------------------------*/
2114 /* Close all handles created by kwsysProcess_Execute. */
2115 void kwsysProcessCleanup(kwsysProcess* cp, int error)
2117 int i;
2118 /* If this is an error case, report the error. */
2119 if(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);
2130 if(length < 1)
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)
2149 if(cp->Win9x)
2151 SetEvent(cp->Win9xKillEvent);
2153 else
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);
2178 /* Free memory. */
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;
2212 --length;
2213 if(length > 0 && cp->ErrorMessage[length-1] == '\r')
2215 cp->ErrorMessage[length-1] = 0;
2216 --length;
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)
2229 int length = 0;
2230 if(cp->Verbatim)
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;
2236 else
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);
2251 return length;
2254 /*--------------------------------------------------------------------------*/
2255 void kwsysProcessComputeCommandLine(kwsysProcess* cp,
2256 char const* const* command,
2257 char* cmd)
2259 if(cp->Verbatim)
2261 /* Copy the verbatim command line into the buffer. */
2262 strcpy(cmd, *command);
2264 else
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. */
2271 if(arg != command)
2273 *cmd++ = ' ';
2276 /* Add the current argument. */
2277 cmd = kwsysSystem_Shell_GetArgumentForWindows(*arg, cmd, 0);
2280 /* Add the terminating null character to the command line. */
2281 *cmd = 0;
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. */
2303 if(userTimeout)
2305 kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent();
2306 kwsysProcessTime userTimeoutLength = kwsysProcessTimeFromDouble(*userTimeout);
2307 kwsysProcessTime userTimeoutTime = kwsysProcessTimeAdd(currentTime,
2308 userTimeoutLength);
2309 if(timeoutTime->QuadPart < 0 ||
2310 kwsysProcessTimeLess(userTimeoutTime, *timeoutTime))
2312 *timeoutTime = userTimeoutTime;
2313 return 1;
2316 return 0;
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. */
2329 return 0;
2331 else
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. */
2346 return 1;
2348 else
2350 /* There is some time left. */
2351 return 0;
2356 /*--------------------------------------------------------------------------*/
2357 kwsysProcessTime kwsysProcessTimeGetCurrent()
2359 kwsysProcessTime current;
2360 FILETIME ft;
2361 GetSystemTimeAsFileTime(&ft);
2362 current.LowPart = ft.dwLowDateTime;
2363 current.HighPart = ft.dwHighDateTime;
2364 return current;
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)
2382 kwsysProcessTime t;
2383 t.QuadPart = (LONGLONG)(d*10000000);
2384 return t;
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;
2398 return out;
2401 /*--------------------------------------------------------------------------*/
2402 kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2)
2404 kwsysProcessTime out;
2405 out.QuadPart = in1.QuadPart - in2.QuadPart;
2406 return out;
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)
2415 switch (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;
2437 #endif
2438 #ifdef STATUS_FLOAT_MULTIPLE_TRAPS
2439 case STATUS_FLOAT_MULTIPLE_TRAPS:
2440 KWSYSPE_CASE(Numerical, "Floating-point exception (multiple traps)"); break;
2441 #endif
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:
2470 default:
2471 cp->ExitException = kwsysProcess_Exception_Other;
2472 sprintf(cp->ExitExceptionString, "Exit code 0x%x\n", code);
2473 break;
2476 #undef KWSYSPE_CASE
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
2494 USHORT Length;
2495 USHORT MaximumLength;
2496 PWSTR Buffer;
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;
2507 ULONG ThreadCount;
2508 ULONG Reserved1[6];
2509 LARGE_INTEGER CreateTime;
2510 LARGE_INTEGER UserTime;
2511 LARGE_INTEGER KernelTime;
2512 UNICODE_STRING ProcessName;
2513 KPRIORITY BasePriority;
2514 ULONG ProcessId;
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
2525 DWORD dwSize;
2526 DWORD cntUsage;
2527 DWORD th32ProcessID;
2528 DWORD th32DefaultHeapID;
2529 DWORD th32ModuleID;
2530 DWORD cntThreads;
2531 DWORD th32ParentProcessID;
2532 LONG pcPriClassBase;
2533 DWORD dwFlags;
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,
2543 ULONG, PULONG);
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. */
2563 int NT4;
2565 /* Implementation functions and data for NT 4. */
2566 ZwQuerySystemInformationType P_ZwQuerySystemInformation;
2567 char* Buffer;
2568 int BufferSize;
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;
2575 HANDLE Snapshot;
2576 PROCESSENTRY32 CurrentEntry;
2579 /*--------------------------------------------------------------------------*/
2580 static kwsysProcess_List* kwsysProcess_List_New(void)
2582 OSVERSIONINFO osv;
2583 kwsysProcess_List* self;
2585 /* Allocate and initialize the list object. */
2586 if(!(self = (kwsysProcess_List*)malloc(sizeof(kwsysProcess_List))))
2588 return 0;
2590 memset(self, 0, sizeof(*self));
2592 /* Select an implementation. */
2593 ZeroMemory(&osv, sizeof(osv));
2594 osv.dwOSVersionInfoSize = sizeof(osv);
2595 GetVersionEx(&osv);
2596 self->NT4 = (osv.dwPlatformId == VER_PLATFORM_WIN32_NT &&
2597 osv.dwMajorVersion < 5)? 1:0;
2599 /* Initialize the selected implementation. */
2600 if(!(self->NT4?
2601 kwsysProcess_List__New_NT4(self) :
2602 kwsysProcess_List__New_Snapshot(self)))
2604 kwsysProcess_List_Delete(self);
2605 return 0;
2608 /* Update to the current set of processes. */
2609 if(!kwsysProcess_List_Update(self))
2611 kwsysProcess_List_Delete(self);
2612 return 0;
2614 return self;
2617 /*--------------------------------------------------------------------------*/
2618 static void kwsysProcess_List_Delete(kwsysProcess_List* self)
2620 if(self)
2622 if(self->NT4)
2624 kwsysProcess_List__Delete_NT4(self);
2626 else
2628 kwsysProcess_List__Delete_Snapshot(self);
2630 free(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
2674 handle. */
2675 HANDLE hNT = GetModuleHandle("ntdll.dll");
2676 if(hNT)
2678 /* Get pointers to the needed API functions. */
2679 self->P_ZwQuerySystemInformation =
2680 ((ZwQuerySystemInformationType)
2681 GetProcAddress(hNT, "ZwQuerySystemInformation"));
2683 if(!self->P_ZwQuerySystemInformation)
2685 return 0;
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. */
2698 if(self->Buffer)
2700 free(self->Buffer);
2704 /*--------------------------------------------------------------------------*/
2705 static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self)
2707 self->CurrentInfo = 0;
2708 for(;;)
2710 /* Query number 5 is for system process list. */
2711 NTSTATUS status =
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);
2718 if(newBuffer)
2720 free(self->Buffer);
2721 self->Buffer = newBuffer;
2722 self->BufferSize = newBufferSize;
2724 else
2726 return 0;
2729 else if(status >= 0)
2731 /* The query succeeded. Initialize traversal of the process list. */
2732 self->CurrentInfo = (PSYSTEM_PROCESS_INFORMATION)self->Buffer;
2733 return 1;
2735 else
2737 /* The query failed. */
2738 return 0;
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));
2753 return 1;
2755 self->CurrentInfo = 0;
2757 return 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
2778 handle. */
2779 HANDLE hKernel = GetModuleHandle("kernel32.dll");
2780 if(hKernel)
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)
2800 if(self->Snapshot)
2802 CloseHandle(self->Snapshot);
2806 /*--------------------------------------------------------------------------*/
2807 static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List* self)
2809 if(self->Snapshot)
2811 CloseHandle(self->Snapshot);
2813 if(!(self->Snapshot =
2814 self->P_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)))
2816 return 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);
2823 self->Snapshot = 0;
2824 return 0;
2826 return 1;
2829 /*--------------------------------------------------------------------------*/
2830 static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List* self)
2832 if(self->Snapshot)
2834 if(self->P_Process32Next(self->Snapshot, &self->CurrentEntry))
2836 return 1;
2838 CloseHandle(self->Snapshot);
2839 self->Snapshot = 0;
2841 return 0;
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);
2860 if(h)
2862 TerminateProcess(h, 255);
2863 WaitForSingleObject(h, INFINITE);
2864 CloseHandle(h);
2868 /*--------------------------------------------------------------------------*/
2869 static void kwsysProcessKillTree(int pid)
2871 kwsysProcess_List* plist = kwsysProcess_List_New();
2872 kwsysProcessKill(pid);
2873 if(plist)
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)
2890 int i;
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
2913 below. */
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);
2935 --cp->PipesLeft;
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);