Changeset 28926 in vbox for trunk/src/VBox/Frontends/VBoxManage
- Timestamp:
- Apr 30, 2010 10:21:00 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r28920 r28926 44 44 #endif 45 45 46 #include <signal.h> 47 46 48 #ifdef RT_OS_DARWIN 47 49 # include <CoreFoundation/CFRunLoop.h> … … 55 57 */ 56 58 /** @todo */ 59 60 /** Set by the signal handler. */ 61 static volatile bool g_fExecCanceled = false; 57 62 58 63 void usageGuestControl(void) … … 65 70 " [--verbose] [--wait-for exit,stdout,stderr||]\n" 66 71 "\n"); 72 } 73 74 /** 75 * Signal handler that sets g_fCanceled. 76 * 77 * This can be executed on any thread in the process, on Windows it may even be 78 * a thread dedicated to delivering this signal. Do not doing anything 79 * unnecessary here. 80 */ 81 static void execProcessSignalHandler(int iSignal) 82 { 83 NOREF(iSignal); 84 ASMAtomicWriteBool(&g_fExecCanceled, true); 67 85 } 68 86 … … 305 323 RTPrintf("Waiting for process to exit ...\n"); 306 324 325 /* setup signal handling if cancelable */ 326 ASSERT(progress); 327 bool fCanceledAlready = false; 328 BOOL fCancelable; 329 HRESULT hrc = progress->COMGETTER(Cancelable)(&fCancelable); 330 if (FAILED(hrc)) 331 fCancelable = FALSE; 332 if (fCancelable) 333 { 334 signal(SIGINT, execProcessSignalHandler); 335 #ifdef SIGBREAK 336 signal(SIGBREAK, execProcessSignalHandler); 337 #endif 338 } 339 307 340 /* Wait for process to exit ... */ 308 ASSERT(progress); 309 rc = progress->WaitForCompletion(have_timeout ? 310 (u32TimeoutMS + 5000) : /* Timeout value + safety counter */ 311 -1 /* Wait forever */); 312 if (FAILED(rc)) 313 { 314 if (u32TimeoutMS) 315 RTPrintf("Process '%s' (PID: %u) did not end within %ums! Wait aborted.\n", 316 Utf8Cmd.raw(), uPID, u32TimeoutMS); 317 break; 318 } 319 else 320 { 321 BOOL completed; 322 CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc); 323 ASSERT(completed); 324 325 LONG iRc; 341 BOOL fCompleted = false; 342 ULONG cbOutputData = 0; 343 SafeArray<BYTE> aOutputData; 344 while (SUCCEEDED(progress->COMGETTER(Completed(&fCompleted)))) 345 { 346 if (cbOutputData <= 0) 347 { 348 if (fCompleted) 349 break; 350 351 if ( have_timeout 352 && RTTimeMilliTS() - u64StartMS > u32TimeoutMS + 5000) 353 { 354 progress->Cancel(); 355 break; 356 } 357 } 358 359 CHECK_ERROR_BREAK(guest, GetProcessOutput(uPID, 0 /* aFlags */, 360 u32TimeoutMS, _64K, ComSafeArrayAsOutParam(aOutputData))); 361 cbOutputData = aOutputData.size(); 362 if (cbOutputData > 0) 363 { 364 /* aOutputData has a platform dependent line ending, standardize on 365 * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on 366 * Windows. Otherwise we end up with CR/CR/LF on Windows. */ 367 ULONG cbOutputDataPrint = cbOutputData; 368 for (BYTE *s = aOutputData.raw(), *d = s; 369 s - aOutputData.raw() < (ssize_t)cbOutputData; 370 s++, d++) 371 { 372 if (*s == '\r') 373 { 374 /* skip over CR, adjust destination */ 375 d--; 376 cbOutputDataPrint--; 377 } 378 else if (s != d) 379 *d = *s; 380 } 381 RTStrmWrite(g_pStdOut, aOutputData.raw(), cbOutputDataPrint); 382 } 383 384 /* process async cancelation. */ 385 if (g_fExecCanceled && !fCanceledAlready) 386 { 387 hrc = progress->Cancel(); 388 if (SUCCEEDED(hrc)) 389 fCanceledAlready = true; 390 else 391 g_fExecCanceled = false; 392 } 393 394 progress->WaitForCompletion(100); 395 } 396 397 /* undo signal handling */ 398 if (fCancelable) 399 { 400 signal(SIGINT, SIG_DFL); 401 #ifdef SIGBREAK 402 signal(SIGBREAK, SIG_DFL); 403 #endif 404 } 405 406 /* Not completed yet? -> Timeout */ 407 if (fCompleted) 408 { 409 LONG iRc = false; 326 410 CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc); 327 411 if (FAILED(iRc)) … … 330 414 rc = progress->COMGETTER(ErrorInfo)(execError.asOutParam()); 331 415 com::ErrorInfo info (execError); 332 RTPrintf(" Process error details:\n");416 RTPrintf("\n\nProcess error details:\n"); 333 417 GluePrintErrorInfo(info); 334 418 RTPrintf("\n"); 335 } 336 419 } 420 } 421 else 422 { 423 RTPrintf("Process timed out!\n"); 424 } 425 426 if (verbose) 427 { 337 428 ULONG uRetStatus, uRetExitCode, uRetFlags; 338 429 CHECK_ERROR_BREAK(guest, GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &uRetStatus)); 339 if (verbose) 340 RTPrintf("Exit code=%u (Status=%u, Flags=%u)\n", uRetExitCode, uRetStatus, uRetFlags); 341 342 /* Print output if wanted. */ 343 if ( waitForStdOut 344 || waitForStdErr) 345 { 346 bool bFound = false; 347 while (true) 348 { 349 SafeArray<BYTE> aOutputData; 350 ULONG cbOutputData; 351 CHECK_ERROR_BREAK(guest, GetProcessOutput(uPID, 0 /* aFlags */, 352 u32TimeoutMS, _64K, ComSafeArrayAsOutParam(aOutputData))); 353 cbOutputData = aOutputData.size(); 354 if (cbOutputData == 0) 355 break; 356 357 if (!bFound && verbose) 358 { 359 RTPrintf("Retrieving output data ...\n"); 360 bFound = true; 361 } 362 363 /* aOutputData has a platform dependent line ending, standardize on 364 * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on 365 * Windows. Otherwise we end up with CR/CR/LF on Windows. */ 366 ULONG cbOutputDataPrint = cbOutputData; 367 for (BYTE *s = aOutputData.raw(), *d = s; 368 s - aOutputData.raw() < (ssize_t)cbOutputData; 369 s++, d++) 370 { 371 if (*s == '\r') 372 { 373 /* skip over CR, adjust destination */ 374 d--; 375 cbOutputDataPrint--; 376 } 377 else if (s != d) 378 *d = *s; 379 } 380 RTStrmWrite(g_pStdOut, aOutputData.raw(), cbOutputDataPrint); 381 } 382 if (!bFound && verbose) 383 RTPrintf("No output data available\n"); 384 } 430 RTPrintf("Exit code=%u (Status=%u, Flags=%u)\n", uRetExitCode, uRetStatus, uRetFlags); 385 431 } 386 432 }
Note:
See TracChangeset
for help on using the changeset viewer.