VirtualBox

Changeset 28926 in vbox


Ignore:
Timestamp:
Apr 30, 2010 10:21:00 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
60889
Message:

Guest Control/VBoxManage,Main: Immediate process output, now also cancelable with signal handling.

Location:
trunk/src/VBox
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp

    r28833 r28926  
    176176                                        pData->uPID, uHandleId, 0 /* u32Flags */,
    177177                                        abBuf, cbRead);
     178        if (RT_FAILURE(rc))
     179        {
     180            VBoxServiceError("Control: Error while sending real-time output data, rc=%Rrc, cbRead=%u, CID=%u, PID=%u\n",
     181                             rc, cbRead, pThread->uClientID, pData->uPID);
     182        }
     183        else
     184        {
    178185#endif
    179         rc = VBoxServiceControlExecWritePipeBuffer(&pData->stdOut, abBuf, cbRead);
    180         if (RT_SUCCESS(rc))
    181         {
    182             /* Make sure we go another poll round in case there was too much data
    183                for the buffer to hold. */
    184             fPollEvt &= RTPOLL_EVT_ERROR;
    185         }
     186            rc = VBoxServiceControlExecWritePipeBuffer(&pData->stdOut, abBuf, cbRead);
     187            if (RT_SUCCESS(rc))
     188            {
     189                /* Make sure we go another poll round in case there was too much data
     190                   for the buffer to hold. */
     191                fPollEvt &= RTPOLL_EVT_ERROR;
     192            }
     193#if 0
     194        }
     195#endif
    186196    }
    187197    else if (RT_FAILURE(rc2))
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp

    r28920 r28926  
    4444#endif
    4545
     46#include <signal.h>
     47
    4648#ifdef RT_OS_DARWIN
    4749# include <CoreFoundation/CFRunLoop.h>
     
    5557 */
    5658/** @todo */
     59
     60/** Set by the signal handler. */
     61static volatile bool    g_fExecCanceled = false;
    5762
    5863void usageGuestControl(void)
     
    6570             "                            [--verbose] [--wait-for exit,stdout,stderr||]\n"
    6671             "\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 */
     81static void execProcessSignalHandler(int iSignal)
     82{
     83    NOREF(iSignal);
     84    ASMAtomicWriteBool(&g_fExecCanceled, true);
    6785}
    6886
     
    305323                    RTPrintf("Waiting for process to exit ...\n");                       
    306324
     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
    307340                /* 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;
    326410                    CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc);
    327411                    if (FAILED(iRc))
     
    330414                        rc = progress->COMGETTER(ErrorInfo)(execError.asOutParam());
    331415                        com::ErrorInfo info (execError);
    332                         RTPrintf("Process error details:\n");
     416                        RTPrintf("\n\nProcess error details:\n");
    333417                        GluePrintErrorInfo(info);
    334418                        RTPrintf("\n");
    335                     }
    336 
     419                    }         
     420                }
     421                else
     422                {
     423                    RTPrintf("Process timed out!\n");
     424                }
     425               
     426                if (verbose)
     427                {
    337428                    ULONG uRetStatus, uRetExitCode, uRetFlags;
    338429                    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);
    385431                }
    386432            }
  • trunk/src/VBox/Main/GuestImpl.cpp

    r28887 r28926  
    478478        /** @todo Copy void* buffer contents! */
    479479
     480        /* Was progress canceled before? */
     481        BOOL fCancelled;
     482        it->pProgress->COMGETTER(Canceled)(&fCancelled);
     483
    480484        /* Do progress handling. */
    481485        Utf8Str errMsg;
     
    487491
    488492            case PROC_STS_TEN: /* Terminated normally. */
    489                 if (!it->pProgress->getCompleted())
     493                if (   !it->pProgress->getCompleted()
     494                    && !fCancelled)
     495                {
    490496                    it->pProgress->notifyComplete(S_OK);
     497                }
    491498                break;
    492499
     
    542549            && errMsg.length())
    543550        {
    544             if (!it->pProgress->getCompleted())
     551            if (   !it->pProgress->getCompleted()
     552                && !fCancelled)
    545553            {
    546554                it->pProgress->notifyComplete(E_FAIL /** @todo Find a better rc! */, COM_IIDOF(IGuest),
     
    719727            rc = progress->init(static_cast<IGuest*>(this),
    720728                                BstrFmt(tr("Executing process")),
    721                                 FALSE);
     729                                TRUE);
    722730        }
    723731        if (FAILED(rc)) return rc;
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette