diff options
Diffstat (limited to 'src/stable')
-rw-r--r-- | src/stable/process.cpp | 347 | ||||
-rw-r--r-- | src/stable/process.h | 25 |
2 files changed, 303 insertions, 69 deletions
diff --git a/src/stable/process.cpp b/src/stable/process.cpp index a98936e..92e7086 100644 --- a/src/stable/process.cpp +++ b/src/stable/process.cpp | |||
@@ -6,23 +6,40 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "bu/process.h" | 8 | #include "bu/process.h" |
9 | #include <sys/types.h> | ||
10 | #include <sys/wait.h> | ||
11 | #include <unistd.h> | 9 | #include <unistd.h> |
12 | #include <stdarg.h> | 10 | #include <stdarg.h> |
13 | #include <signal.h> | 11 | |
12 | #ifndef WIN32 | ||
13 | #include <sys/wait.h> | ||
14 | #include <sys/types.h> | ||
14 | #include <fcntl.h> | 15 | #include <fcntl.h> |
16 | #include <signal.h> | ||
17 | #include <sys/select.h> | ||
15 | #include <errno.h> | 18 | #include <errno.h> |
19 | #else | ||
20 | #include <windows.h> | ||
21 | #include <tchar.h> | ||
22 | #include <wchar.h> | ||
23 | #endif | ||
16 | 24 | ||
17 | #include <sys/select.h> | ||
18 | 25 | ||
19 | #include "bu/config.h" | 26 | #include "bu/config.h" |
20 | 27 | ||
21 | Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) : | 28 | Bu::Process::ProcData::ProcData() : |
29 | #ifdef WIN32 | ||
30 | hStdIn( NULL ), | ||
31 | hStdOut( NULL ), | ||
32 | hStdErr( NULL ) | ||
33 | #else | ||
22 | iStdIn( -1 ), | 34 | iStdIn( -1 ), |
23 | iStdOut( -1 ), | 35 | iStdOut( -1 ), |
24 | iStdErr( -1 ), | 36 | iStdErr( -1 ) |
25 | iPid( 0 ), | 37 | #endif |
38 | { | ||
39 | } | ||
40 | |||
41 | |||
42 | Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) : | ||
26 | iProcStatus( 0 ), | 43 | iProcStatus( 0 ), |
27 | bBlocking( true ), | 44 | bBlocking( true ), |
28 | bStdOutEos( true ), | 45 | bStdOutEos( true ), |
@@ -32,10 +49,6 @@ Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) : | |||
32 | } | 49 | } |
33 | 50 | ||
34 | Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) : | 51 | Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) : |
35 | iStdIn( -1 ), | ||
36 | iStdOut( -1 ), | ||
37 | iStdErr( -1 ), | ||
38 | iPid( 0 ), | ||
39 | iProcStatus( 0 ), | 52 | iProcStatus( 0 ), |
40 | bBlocking( true ), | 53 | bBlocking( true ), |
41 | bStdOutEos( true ), | 54 | bStdOutEos( true ), |
@@ -62,10 +75,6 @@ Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) : | |||
62 | } | 75 | } |
63 | 76 | ||
64 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, char *const argv[] ) : | 77 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, char *const argv[] ) : |
65 | iStdIn( -1 ), | ||
66 | iStdOut( -1 ), | ||
67 | iStdErr( -1 ), | ||
68 | iPid( 0 ), | ||
69 | iProcStatus( 0 ), | 78 | iProcStatus( 0 ), |
70 | bBlocking( true ), | 79 | bBlocking( true ), |
71 | bStdOutEos( true ), | 80 | bStdOutEos( true ), |
@@ -76,10 +85,6 @@ Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char | |||
76 | } | 85 | } |
77 | 86 | ||
78 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, const char *argv, ...) : | 87 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, const char *argv, ...) : |
79 | iStdIn( -1 ), | ||
80 | iStdOut( -1 ), | ||
81 | iStdErr( -1 ), | ||
82 | iPid( 0 ), | ||
83 | iProcStatus( 0 ), | 88 | iProcStatus( 0 ), |
84 | bBlocking( true ), | 89 | bBlocking( true ), |
85 | bStdOutEos( true ), | 90 | bStdOutEos( true ), |
@@ -118,6 +123,102 @@ void Bu::Process::wait() | |||
118 | 123 | ||
119 | void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] ) | 124 | void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] ) |
120 | { | 125 | { |
126 | #ifdef WIN32 | ||
127 | bStdErrEos = true; | ||
128 | SECURITY_ATTRIBUTES saAttr; | ||
129 | HANDLE hChildStd_IN_Rd; | ||
130 | HANDLE hChildStd_IN_Wr; | ||
131 | HANDLE hChildStd_OUT_Rd; | ||
132 | HANDLE hChildStd_OUT_Wr; | ||
133 | |||
134 | saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); | ||
135 | saAttr.bInheritHandle = TRUE; | ||
136 | saAttr.lpSecurityDescriptor = NULL; | ||
137 | |||
138 | // Create a pipe for the child process's STDOUT. | ||
139 | if ( ! CreatePipe( | ||
140 | &hChildStd_OUT_Rd, | ||
141 | &hChildStd_OUT_Wr, | ||
142 | &saAttr, 0) ) | ||
143 | throw "StdoutRd CreatePipe"; | ||
144 | |||
145 | // Ensure the read handle to the pipe for STDOUT is not inherited. | ||
146 | if ( ! SetHandleInformation( | ||
147 | hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) ) | ||
148 | throw "Stdout SetHandleInformation"; | ||
149 | |||
150 | // Create a pipe for the child process's STDIN. | ||
151 | if (! CreatePipe( | ||
152 | &hChildStd_IN_Rd, | ||
153 | &hChildStd_IN_Wr, | ||
154 | &saAttr, 0)) | ||
155 | throw "Stdin CreatePipe"; | ||
156 | |||
157 | // Ensure the write handle to the pipe for STDIN is not inherited. | ||
158 | if ( ! SetHandleInformation( | ||
159 | hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) ) | ||
160 | throw "Stdin SetHandleInformation"; | ||
161 | |||
162 | //TCHAR szCmdline[] = TEXT( sName ); | ||
163 | //PROCESS_INFORMATION pd.piProcInfo; | ||
164 | STARTUPINFO siStartInfo; | ||
165 | BOOL bSuccess = FALSE; | ||
166 | |||
167 | // Set up members of the PROCESS_INFORMATION structure. | ||
168 | ZeroMemory( &pd.piProcInfo, sizeof(PROCESS_INFORMATION) ); | ||
169 | |||
170 | // Set up members of the STARTUPINFO structure. | ||
171 | // This structure specifies the STDIN and STDOUT handles for redirection. | ||
172 | ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); | ||
173 | siStartInfo.cb = sizeof(STARTUPINFO); | ||
174 | siStartInfo.hStdError = hChildStd_OUT_Wr; | ||
175 | siStartInfo.hStdOutput = hChildStd_OUT_Wr; | ||
176 | siStartInfo.hStdInput = hChildStd_IN_Rd; | ||
177 | siStartInfo.dwFlags |= STARTF_USESTDHANDLES; | ||
178 | |||
179 | Bu::String sCmd; | ||
180 | for( char *const *arg = argv; *arg; arg++ ) | ||
181 | { | ||
182 | if( arg != argv ) | ||
183 | sCmd += " "; | ||
184 | sCmd += *arg; | ||
185 | } | ||
186 | |||
187 | // Create the child process. | ||
188 | bSuccess = CreateProcessA( | ||
189 | sName, //sName, //module name | ||
190 | sCmd.getStr(), //(TCHAR *) sName, //szCmdline, // command line | ||
191 | NULL, // process security attributes | ||
192 | NULL, // primary thread security attributes | ||
193 | TRUE, // handles are inherited | ||
194 | CREATE_NO_WINDOW, // creation flags | ||
195 | NULL, // use parent's environment | ||
196 | NULL, // use parent's current directory | ||
197 | &siStartInfo, // STARTUPINFO pointer | ||
198 | &pd.piProcInfo ); // receives PROCESS_INFORMATION | ||
199 | |||
200 | // If an error occurs, exit the application. | ||
201 | if ( ! bSuccess ) | ||
202 | { | ||
203 | throw Bu::ExceptionBase("Error spawning child process."); | ||
204 | return; | ||
205 | } | ||
206 | else | ||
207 | { | ||
208 | // Close handles to the child process and its primary thread. | ||
209 | // Some applications might keep these handles to monitor the status | ||
210 | // of the child process, for example. | ||
211 | |||
212 | //CloseHandle(pData->pd.piProcInfo.hProcess); | ||
213 | CloseHandle(pd.piProcInfo.hThread); | ||
214 | |||
215 | // Close the ends we can't use | ||
216 | CloseHandle( hChildStd_OUT_Wr ); | ||
217 | CloseHandle( hChildStd_IN_Rd ); | ||
218 | pd.hStdIn = hChildStd_IN_Wr; | ||
219 | pd.hStdOut = hChildStd_OUT_Rd; | ||
220 | } | ||
221 | #else | ||
121 | int iaStdIn[2]; | 222 | int iaStdIn[2]; |
122 | int iaStdOut[2]; | 223 | int iaStdOut[2]; |
123 | int iaStdErr[2]; | 224 | int iaStdErr[2]; |
@@ -125,22 +226,22 @@ void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] ) | |||
125 | if( eFlags & StdOut ) | 226 | if( eFlags & StdOut ) |
126 | { | 227 | { |
127 | pipe( iaStdOut ); | 228 | pipe( iaStdOut ); |
128 | iStdOut = iaStdOut[0]; | 229 | pd.iStdOut = iaStdOut[0]; |
129 | bStdOutEos = false; | 230 | bStdOutEos = false; |
130 | } | 231 | } |
131 | if( eFlags & StdErr ) | 232 | if( eFlags & StdErr ) |
132 | { | 233 | { |
133 | pipe( iaStdErr ); | 234 | pipe( iaStdErr ); |
134 | iStdErr = iaStdErr[0]; | 235 | pd.iStdErr = iaStdErr[0]; |
135 | bStdErrEos = false; | 236 | bStdErrEos = false; |
136 | } | 237 | } |
137 | 238 | ||
138 | iStdIn = iaStdIn[1]; | 239 | pd.iStdIn = iaStdIn[1]; |
139 | 240 | ||
140 | // fcntl( iStdOut, F_SETFL, fcntl( iStdOut, F_GETFL, 0 )|O_NONBLOCK ); | 241 | // fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK ); |
141 | 242 | ||
142 | iPid = fork(); | 243 | pd.iPid = fork(); |
143 | if( iPid == 0 ) | 244 | if( pd.iPid == 0 ) |
144 | { | 245 | { |
145 | ::close( iaStdIn[1] ); | 246 | ::close( iaStdIn[1] ); |
146 | dup2( iaStdIn[0], 0 ); | 247 | dup2( iaStdIn[0], 0 ); |
@@ -170,48 +271,97 @@ void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] ) | |||
170 | ::close( iaStdOut[1] ); | 271 | ::close( iaStdOut[1] ); |
171 | if( eFlags & StdErr ) | 272 | if( eFlags & StdErr ) |
172 | ::close( iaStdErr[1] ); | 273 | ::close( iaStdErr[1] ); |
274 | #endif | ||
173 | } | 275 | } |
174 | 276 | ||
175 | void Bu::Process::close() | 277 | void Bu::Process::close() |
176 | { | 278 | { |
177 | if( iPid ) | 279 | #ifdef WIN32 |
280 | if( pd.hStdIn ) | ||
281 | { | ||
282 | CloseHandle( pd.hStdIn ); | ||
283 | CloseHandle( pd.hStdOut ); | ||
284 | |||
285 | pd.hStdIn = pd.hStdOut = pd.hStdErr = NULL; | ||
286 | |||
287 | if( !TerminateProcess(pd.piProcInfo.hProcess, 1) ) | ||
288 | { | ||
289 | throw Bu::ExceptionBase("Error closing process."); | ||
290 | } | ||
291 | |||
292 | GetExitCodeProcess( pd.piProcInfo.hProcess, (PDWORD)&iProcStatus ); | ||
293 | |||
294 | CloseHandle( pd.piProcInfo.hProcess ); | ||
295 | pd.piProcInfo.hProcess = NULL; | ||
296 | } | ||
297 | #else | ||
298 | if( pd.iPid ) | ||
178 | { | 299 | { |
179 | if( iStdIn > -1 ) | 300 | if( pd.iStdIn > -1 ) |
180 | ::close( iStdIn ); | 301 | ::close( pd.iStdIn ); |
181 | if( iStdOut > -1 ) | 302 | if( pd.iStdOut > -1 ) |
182 | ::close( iStdOut ); | 303 | ::close( pd.iStdOut ); |
183 | if( iStdErr > -1 ) | 304 | if( pd.iStdErr > -1 ) |
184 | ::close( iStdErr ); | 305 | ::close( pd.iStdErr ); |
185 | waitpid( iPid, &iProcStatus, 0 ); | 306 | waitpid( pd.iPid, &iProcStatus, 0 ); |
186 | iPid = 0; | 307 | pd.iPid = 0; |
187 | } | 308 | } |
309 | #endif | ||
188 | } | 310 | } |
189 | 311 | ||
190 | void Bu::Process::closeStdIn() | 312 | void Bu::Process::closeStdIn() |
191 | { | 313 | { |
192 | ::close( iStdIn ); | 314 | #ifdef WIN32 |
193 | iStdIn = -1; | 315 | CloseHandle( pd.hStdIn ); |
316 | pd.hStdIn = NULL; | ||
317 | #else | ||
318 | ::close( pd.iStdIn ); | ||
319 | pd.iStdIn = -1; | ||
320 | #endif | ||
194 | } | 321 | } |
195 | 322 | ||
196 | void Bu::Process::closeStdOut() | 323 | void Bu::Process::closeStdOut() |
197 | { | 324 | { |
198 | ::close( iStdOut ); | 325 | #ifdef WIN32 |
199 | iStdOut = -1; | 326 | CloseHandle( pd.hStdOut ); |
327 | pd.hStdOut = NULL; | ||
328 | #else | ||
329 | ::close( pd.iStdOut ); | ||
330 | pd.iStdOut = -1; | ||
331 | #endif | ||
200 | } | 332 | } |
201 | 333 | ||
202 | Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes ) | 334 | Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes ) |
203 | { | 335 | { |
336 | #ifdef WIN32 | ||
337 | DWORD dwRead; | ||
338 | DWORD lExitCode; | ||
339 | BOOL bSuccess = FALSE; | ||
340 | DWORD dwLen = (DWORD) nBytes; | ||
341 | bSuccess = ReadFile( | ||
342 | pd.hStdOut, (char *) pBuf, | ||
343 | dwLen, &dwRead, NULL); | ||
344 | // if( dwRead < dwLen ) | ||
345 | { | ||
346 | bSuccess = GetExitCodeProcess( pd.piProcInfo.hProcess, &lExitCode ); | ||
347 | if( lExitCode != STILL_ACTIVE ) | ||
348 | { | ||
349 | bStdOutEos = true; | ||
350 | } | ||
351 | } | ||
352 | return (int32_t) dwRead; | ||
353 | #else | ||
204 | if( bStdOutEos ) | 354 | if( bStdOutEos ) |
205 | return 0; | 355 | return 0; |
206 | fd_set rfds; | 356 | fd_set rfds; |
207 | FD_ZERO( &rfds ); | 357 | FD_ZERO( &rfds ); |
208 | FD_SET( iStdOut, &rfds ); | 358 | FD_SET( pd.iStdOut, &rfds ); |
209 | struct timeval tv = {0, 0}; | 359 | struct timeval tv = {0, 0}; |
210 | if( ::bu_select( iStdOut+1, &rfds, NULL, NULL, &tv ) < 0 ) | 360 | if( ::bu_select( pd.iStdOut+1, &rfds, NULL, NULL, &tv ) < 0 ) |
211 | throw Bu::ExceptionBase( strerror( errno ) ); | 361 | throw Bu::ExceptionBase( strerror( errno ) ); |
212 | if( FD_ISSET( iStdOut, &rfds ) || bBlocking ) | 362 | if( FD_ISSET( pd.iStdOut, &rfds ) || bBlocking ) |
213 | { | 363 | { |
214 | Bu::size nRead = TEMP_FAILURE_RETRY( ::read( iStdOut, pBuf, nBytes ) ); | 364 | Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdOut, pBuf, nBytes ) ); |
215 | if( nRead == 0 ) | 365 | if( nRead == 0 ) |
216 | { | 366 | { |
217 | bStdOutEos = true; | 367 | bStdOutEos = true; |
@@ -227,21 +377,33 @@ Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes ) | |||
227 | return nRead; | 377 | return nRead; |
228 | } | 378 | } |
229 | return 0; | 379 | return 0; |
380 | #endif | ||
230 | } | 381 | } |
231 | 382 | ||
232 | Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes ) | 383 | Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes ) |
233 | { | 384 | { |
385 | #ifdef WIN32 | ||
386 | if( !pd.hStdErr ) | ||
387 | return 0; | ||
388 | DWORD dwRead; | ||
389 | BOOL bSuccess = FALSE; | ||
390 | DWORD dwLen = (DWORD) nBytes; | ||
391 | bSuccess = ReadFile( | ||
392 | pd.hStdErr, (char *) pBuf, | ||
393 | dwLen, &dwRead, NULL); | ||
394 | return (int32_t) dwRead; | ||
395 | #else | ||
234 | if( bStdErrEos ) | 396 | if( bStdErrEos ) |
235 | return 0; | 397 | return 0; |
236 | fd_set rfds; | 398 | fd_set rfds; |
237 | FD_ZERO( &rfds ); | 399 | FD_ZERO( &rfds ); |
238 | FD_SET( iStdErr, &rfds ); | 400 | FD_SET( pd.iStdErr, &rfds ); |
239 | struct timeval tv = {0, 0}; | 401 | struct timeval tv = {0, 0}; |
240 | if( ::bu_select( iStdErr+1, &rfds, NULL, NULL, &tv ) < 0 ) | 402 | if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, &tv ) < 0 ) |
241 | throw Bu::ExceptionBase( strerror( errno ) ); | 403 | throw Bu::ExceptionBase( strerror( errno ) ); |
242 | if( FD_ISSET( iStdErr, &rfds ) || bBlocking ) | 404 | if( FD_ISSET( pd.iStdErr, &rfds ) || bBlocking ) |
243 | { | 405 | { |
244 | Bu::size nRead = TEMP_FAILURE_RETRY( ::read( iStdErr, pBuf, nBytes ) ); | 406 | Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdErr, pBuf, nBytes ) ); |
245 | if( nRead == 0 ) | 407 | if( nRead == 0 ) |
246 | { | 408 | { |
247 | bStdErrEos = true; | 409 | bStdErrEos = true; |
@@ -257,11 +419,23 @@ Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes ) | |||
257 | return nRead; | 419 | return nRead; |
258 | } | 420 | } |
259 | return 0; | 421 | return 0; |
422 | #endif | ||
260 | } | 423 | } |
261 | 424 | ||
262 | Bu::size Bu::Process::write( const void *pBuf, Bu::size nBytes ) | 425 | Bu::size Bu::Process::write( const void *pBuf, Bu::size nBytes ) |
263 | { | 426 | { |
264 | return TEMP_FAILURE_RETRY( ::write( iStdIn, pBuf, nBytes ) ); | 427 | #ifdef WIN32 |
428 | DWORD dwWritten; | ||
429 | BOOL bSuccess = FALSE; | ||
430 | DWORD dwLen = (DWORD) nBytes; | ||
431 | bSuccess = WriteFile( | ||
432 | pd.hStdIn, (const char *) pBuf, | ||
433 | dwLen, &dwWritten, NULL ); | ||
434 | FlushFileBuffers( pd.hStdIn ); | ||
435 | return (int32_t) dwWritten; | ||
436 | #else | ||
437 | return TEMP_FAILURE_RETRY( ::write( pd.iStdIn, pBuf, nBytes ) ); | ||
438 | #endif | ||
265 | } | 439 | } |
266 | 440 | ||
267 | Bu::size Bu::Process::tell() | 441 | Bu::size Bu::Process::tell() |
@@ -283,12 +457,16 @@ void Bu::Process::setPosEnd( Bu::size ) | |||
283 | 457 | ||
284 | bool Bu::Process::isEos() | 458 | bool Bu::Process::isEos() |
285 | { | 459 | { |
286 | return (iPid == 0); | 460 | #ifdef WIN32 |
461 | return (pd.piProcInfo.hProcess == NULL); | ||
462 | #else | ||
463 | return (pd.iPid == 0); | ||
464 | #endif | ||
287 | } | 465 | } |
288 | 466 | ||
289 | bool Bu::Process::isOpen() | 467 | bool Bu::Process::isOpen() |
290 | { | 468 | { |
291 | return (iPid != 0); | 469 | return !isEos(); |
292 | } | 470 | } |
293 | 471 | ||
294 | void Bu::Process::flush() | 472 | void Bu::Process::flush() |
@@ -327,21 +505,24 @@ bool Bu::Process::isBlocking() | |||
327 | 505 | ||
328 | void Bu::Process::setBlocking( bool bBlocking ) | 506 | void Bu::Process::setBlocking( bool bBlocking ) |
329 | { | 507 | { |
508 | #ifdef WIN32 | ||
509 | #else | ||
330 | if( bBlocking ) | 510 | if( bBlocking ) |
331 | { | 511 | { |
332 | if( !bStdOutEos ) | 512 | if( !bStdOutEos ) |
333 | fcntl( iStdOut, F_SETFL, fcntl(iStdOut,F_GETFL,0 )&(~O_NONBLOCK) ); | 513 | fcntl( pd.iStdOut, F_SETFL, fcntl(pd.iStdOut,F_GETFL,0 )&(~O_NONBLOCK) ); |
334 | if( !bStdErrEos ) | 514 | if( !bStdErrEos ) |
335 | fcntl( iStdErr, F_SETFL, fcntl(iStdErr,F_GETFL,0 )&(~O_NONBLOCK) ); | 515 | fcntl( pd.iStdErr, F_SETFL, fcntl(pd.iStdErr,F_GETFL,0 )&(~O_NONBLOCK) ); |
336 | } | 516 | } |
337 | else | 517 | else |
338 | { | 518 | { |
339 | if( !bStdOutEos ) | 519 | if( !bStdOutEos ) |
340 | fcntl( iStdOut, F_SETFL, fcntl( iStdOut, F_GETFL, 0 )|O_NONBLOCK ); | 520 | fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK ); |
341 | if( !bStdErrEos ) | 521 | if( !bStdErrEos ) |
342 | fcntl( iStdErr, F_SETFL, fcntl( iStdErr, F_GETFL, 0 )|O_NONBLOCK ); | 522 | fcntl( pd.iStdErr, F_SETFL, fcntl( pd.iStdErr, F_GETFL, 0 )|O_NONBLOCK ); |
343 | } | 523 | } |
344 | this->bBlocking = bBlocking; | 524 | this->bBlocking = bBlocking; |
525 | #endif | ||
345 | } | 526 | } |
346 | 527 | ||
347 | void Bu::Process::setSize( Bu::size ) | 528 | void Bu::Process::setSize( Bu::size ) |
@@ -365,70 +546,107 @@ Bu::String Bu::Process::getLocation() const | |||
365 | 546 | ||
366 | void Bu::Process::select( bool &bStdOut, bool &bStdErr ) | 547 | void Bu::Process::select( bool &bStdOut, bool &bStdErr ) |
367 | { | 548 | { |
549 | #ifdef WIN32 | ||
550 | #else | ||
368 | fd_set rfds; | 551 | fd_set rfds; |
369 | FD_ZERO( &rfds ); | 552 | FD_ZERO( &rfds ); |
370 | if( !bStdOutEos ) | 553 | if( !bStdOutEos ) |
371 | FD_SET( iStdOut, &rfds ); | 554 | FD_SET( pd.iStdOut, &rfds ); |
372 | if( !bStdErrEos ) | 555 | if( !bStdErrEos ) |
373 | FD_SET( iStdErr, &rfds ); | 556 | FD_SET( pd.iStdErr, &rfds ); |
374 | if( ::bu_select( iStdErr+1, &rfds, NULL, NULL, NULL ) < 0 ) | 557 | if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, NULL ) < 0 ) |
375 | throw Bu::ExceptionBase( strerror( errno ) ); | 558 | throw Bu::ExceptionBase( strerror( errno ) ); |
376 | 559 | ||
377 | if( FD_ISSET( iStdOut, &rfds ) ) | 560 | if( FD_ISSET( pd.iStdOut, &rfds ) ) |
378 | bStdOut = true; | 561 | bStdOut = true; |
379 | else | 562 | else |
380 | bStdOut = false; | 563 | bStdOut = false; |
381 | 564 | ||
382 | if( FD_ISSET( iStdErr, &rfds ) ) | 565 | if( FD_ISSET( pd.iStdErr, &rfds ) ) |
383 | bStdErr = true; | 566 | bStdErr = true; |
384 | else | 567 | else |
385 | bStdErr = false; | 568 | bStdErr = false; |
569 | #endif | ||
386 | } | 570 | } |
387 | 571 | ||
388 | bool Bu::Process::isRunning() | 572 | bool Bu::Process::isRunning() |
389 | { | 573 | { |
390 | if( waitpid( iPid, NULL, WNOHANG ) == iPid ) | 574 | #ifdef WIN32 |
575 | DWORD lExitCode; | ||
576 | GetExitCodeProcess( pd.piProcInfo.hProcess, &lExitCode ); | ||
577 | if( lExitCode != STILL_ACTIVE ) | ||
391 | checkClose(); | 578 | checkClose(); |
392 | return iPid != 0; | 579 | #else |
580 | if( waitpid( pd.iPid, NULL, WNOHANG ) == pd.iPid ) | ||
581 | checkClose(); | ||
582 | #endif | ||
583 | return isOpen(); | ||
393 | } | 584 | } |
394 | 585 | ||
395 | void Bu::Process::ignoreStdErr() | 586 | void Bu::Process::ignoreStdErr() |
396 | { | 587 | { |
397 | if( iStdErr == -1 ) | 588 | #ifdef WIN32 |
589 | #else | ||
590 | if( pd.iStdErr == -1 ) | ||
398 | return; | 591 | return; |
399 | ::close( iStdErr ); | 592 | ::close( pd.iStdErr ); |
400 | iStdErr = -1; | 593 | pd.iStdErr = -1; |
401 | bStdErrEos = true; | 594 | bStdErrEos = true; |
595 | #endif | ||
402 | } | 596 | } |
403 | 597 | ||
404 | pid_t Bu::Process::getPid() | 598 | pid_t Bu::Process::getPid() |
405 | { | 599 | { |
406 | return iPid; | 600 | #ifdef WIN32 |
601 | return 0; | ||
602 | #else | ||
603 | return pd.iPid; | ||
604 | #endif | ||
407 | } | 605 | } |
408 | 606 | ||
409 | bool Bu::Process::childExited() | 607 | bool Bu::Process::childExited() |
410 | { | 608 | { |
609 | #ifdef WIN32 | ||
610 | return pd.piProcInfo.hProcess != NULL; | ||
611 | #else | ||
411 | return WIFEXITED( iProcStatus ); | 612 | return WIFEXITED( iProcStatus ); |
613 | #endif | ||
412 | } | 614 | } |
413 | 615 | ||
414 | int Bu::Process::childExitStatus() | 616 | int Bu::Process::childExitStatus() |
415 | { | 617 | { |
618 | #ifdef WIN32 | ||
619 | return iProcStatus; | ||
620 | #else | ||
416 | return WEXITSTATUS( iProcStatus ); | 621 | return WEXITSTATUS( iProcStatus ); |
622 | #endif | ||
417 | } | 623 | } |
418 | 624 | ||
419 | bool Bu::Process::childSignaled() | 625 | bool Bu::Process::childSignaled() |
420 | { | 626 | { |
627 | #ifdef WIN32 | ||
628 | return false; | ||
629 | #else | ||
421 | return WIFSIGNALED( iProcStatus ); | 630 | return WIFSIGNALED( iProcStatus ); |
631 | #endif | ||
422 | } | 632 | } |
423 | 633 | ||
424 | int Bu::Process::childSignal() | 634 | int Bu::Process::childSignal() |
425 | { | 635 | { |
636 | #ifdef WIN32 | ||
637 | return 0; | ||
638 | #else | ||
426 | return WTERMSIG( iProcStatus ); | 639 | return WTERMSIG( iProcStatus ); |
640 | #endif | ||
427 | } | 641 | } |
428 | 642 | ||
429 | bool Bu::Process::childCoreDumped() | 643 | bool Bu::Process::childCoreDumped() |
430 | { | 644 | { |
645 | #ifdef WIN32 | ||
646 | return false; | ||
647 | #else | ||
431 | return WCOREDUMP( iProcStatus ); | 648 | return WCOREDUMP( iProcStatus ); |
649 | #endif | ||
432 | } | 650 | } |
433 | 651 | ||
434 | void Bu::Process::checkClose() | 652 | void Bu::Process::checkClose() |
@@ -438,4 +656,3 @@ void Bu::Process::checkClose() | |||
438 | close(); | 656 | close(); |
439 | } | 657 | } |
440 | } | 658 | } |
441 | |||
diff --git a/src/stable/process.h b/src/stable/process.h index d6282e0..f010633 100644 --- a/src/stable/process.h +++ b/src/stable/process.h | |||
@@ -8,6 +8,10 @@ | |||
8 | #ifndef BU_PROCESS_H | 8 | #ifndef BU_PROCESS_H |
9 | #define BU_PROCESS_H | 9 | #define BU_PROCESS_H |
10 | 10 | ||
11 | #ifdef WIN32 | ||
12 | #include <windows.h> | ||
13 | #endif | ||
14 | |||
11 | #include <stdint.h> | 15 | #include <stdint.h> |
12 | #include <sys/types.h> | 16 | #include <sys/types.h> |
13 | 17 | ||
@@ -135,10 +139,23 @@ namespace Bu | |||
135 | bool childCoreDumped(); | 139 | bool childCoreDumped(); |
136 | 140 | ||
137 | private: | 141 | private: |
138 | int iStdIn; | 142 | class ProcData |
139 | int iStdOut; | 143 | { |
140 | int iStdErr; | 144 | public: |
141 | pid_t iPid; | 145 | ProcData(); |
146 | #ifdef WIN32 | ||
147 | void *hStdIn; | ||
148 | void *hStdOut; | ||
149 | void *hStdErr; | ||
150 | PROCESS_INFORMATION piProcInfo; | ||
151 | #else | ||
152 | int iStdIn; | ||
153 | int iStdOut; | ||
154 | int iStdErr; | ||
155 | pid_t iPid; | ||
156 | #endif | ||
157 | }; | ||
158 | ProcData pd; | ||
142 | int iProcStatus; | 159 | int iProcStatus; |
143 | bool bBlocking; | 160 | bool bBlocking; |
144 | bool bStdOutEos; | 161 | bool bStdOutEos; |