~cjohnston/ubuntu/raring/virtualbox/fix-for-1101867

« back to all changes in this revision

Viewing changes to src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2012-04-05 12:41:55 UTC
  • mfrom: (3.1.12 sid)
  • Revision ID: package-import@ubuntu.com-20120405124155-i7b39tv5ddwhubbe
Tags: 4.1.12-dfsg-2
* Upstream has replaced the 4.1.12 tarball with a new one that fixes a
  crash when creating host only interfaces. (Closes: #667460)
  - Add 36-tarball-respin.patch which contains the diff between the old
    and the new tarball.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 */
5
5
 
6
6
/*
7
 
 * Copyright (C) 2011 Oracle Corporation
 
7
 * Copyright (C) 2012 Oracle Corporation
8
8
 *
9
9
 * This file is part of VirtualBox Open Source Edition (OSE), as
10
10
 * available from http://www.virtualbox.org. This file is free software;
117
117
    {
118
118
        if (rc == VERR_HGCM_SERVICE_NOT_FOUND) /* Host service is not available. */
119
119
        {
120
 
            VBoxServiceVerbose(0, "Control: Guest property service is not available, skipping\n");
 
120
            VBoxServiceVerbose(0, "Guest property service is not available, skipping\n");
121
121
            rc = VINF_SUCCESS;
122
122
        }
123
123
        else
124
 
            VBoxServiceError("Control: Failed to connect to the guest property service! Error: %Rrc\n", rc);
 
124
            VBoxServiceError("Failed to connect to the guest property service! Error: %Rrc\n", rc);
125
125
    }
126
126
    else
127
127
    {
185
185
    rc = VbglR3GuestCtrlConnect(&g_uControlSvcClientID);
186
186
    if (RT_SUCCESS(rc))
187
187
    {
188
 
        VBoxServiceVerbose(3, "Control: Service client ID: %#x\n", g_uControlSvcClientID);
 
188
        VBoxServiceVerbose(3, "Service client ID: %#x\n", g_uControlSvcClientID);
189
189
 
190
190
        /* Init thread lists. */
191
191
        RTListInit(&g_lstControlThreadsActive);
201
201
           causing VBoxService to fail. */
202
202
        if (rc == VERR_HGCM_SERVICE_NOT_FOUND) /* Host service is not available. */
203
203
        {
204
 
            VBoxServiceVerbose(0, "Control: Guest control service is not available\n");
 
204
            VBoxServiceVerbose(0, "Guest control service is not available\n");
205
205
            rc = VERR_SERVICE_DISABLED;
206
206
        }
207
207
        else
208
 
            VBoxServiceError("Control: Failed to connect to the guest control service! Error: %Rrc\n", rc);
 
208
            VBoxServiceError("Failed to connect to the guest control service! Error: %Rrc\n", rc);
209
209
        RTSemEventMultiDestroy(g_hControlEvent);
210
210
        g_hControlEvent = NIL_RTSEMEVENTMULTI;
211
211
    }
232
232
     */
233
233
    for (;;)
234
234
    {
235
 
        VBoxServiceVerbose(3, "Control: Waiting for host msg ...\n");
236
 
        uint32_t uMsg;
237
 
        uint32_t cParms;
 
235
        VBoxServiceVerbose(3, "Waiting for host msg ...\n");
 
236
        uint32_t uMsg = 0;
 
237
        uint32_t cParms = 0;
238
238
        rc = VbglR3GuestCtrlWaitForHostMsg(g_uControlSvcClientID, &uMsg, &cParms);
239
239
        if (rc == VERR_TOO_MUCH_DATA)
240
240
        {
241
 
            VBoxServiceVerbose(4, "Control: Message requires %ld parameters, but only 2 supplied -- retrying request (no error!)...\n", cParms);
 
241
            VBoxServiceVerbose(4, "Message requires %ld parameters, but only 2 supplied -- retrying request (no error!)...\n", cParms);
242
242
            rc = VINF_SUCCESS; /* Try to get "real" message in next block below. */
243
243
        }
244
244
        else if (RT_FAILURE(rc))
245
 
            VBoxServiceVerbose(3, "Control: Getting host message failed with %Rrc\n", rc); /* VERR_GEN_IO_FAILURE seems to be normal if ran into timeout. */
 
245
            VBoxServiceVerbose(3, "Getting host message failed with %Rrc\n", rc); /* VERR_GEN_IO_FAILURE seems to be normal if ran into timeout. */
246
246
        if (RT_SUCCESS(rc))
247
247
        {
248
 
            VBoxServiceVerbose(3, "Control: Msg=%u (%u parms) retrieved\n", uMsg, cParms);
 
248
            VBoxServiceVerbose(3, "Msg=%u (%u parms) retrieved\n", uMsg, cParms);
249
249
            switch (uMsg)
250
250
            {
251
251
                case HOST_CANCEL_PENDING_WAITS:
252
 
                    VBoxServiceVerbose(3, "Control: Host asked us to quit ...\n");
 
252
                    VBoxServiceVerbose(3, "Host asked us to quit ...\n");
253
253
                    break;
254
254
 
255
255
                case HOST_EXEC_CMD:
266
266
                    break;
267
267
 
268
268
                default:
269
 
                    VBoxServiceVerbose(3, "Control: Unsupported message from host! Msg=%u\n", uMsg);
 
269
                    VBoxServiceVerbose(3, "Unsupported message from host! Msg=%u\n", uMsg);
270
270
                    /* Don't terminate here; just wait for the next message. */
271
271
                    break;
272
272
            }
324
324
                                               &proc.uTimeLimitMS);
325
325
        if (RT_SUCCESS(rc))
326
326
        {
327
 
            VBoxServiceVerbose(3, "Control: Request to start process szCmd=%s, uFlags=0x%x, szArgs=%s, szEnv=%s, szUser=%s, uTimeout=%u\n",
 
327
            VBoxServiceVerbose(3, "Request to start process szCmd=%s, uFlags=0x%x, szArgs=%s, szEnv=%s, szUser=%s, uTimeout=%u\n",
328
328
                               proc.szCmd, proc.uFlags,
329
329
                               proc.uNumArgs ? proc.szArgs : "<None>",
330
330
                               proc.uNumEnvVars ? proc.szEnv : "<None>",
332
332
 
333
333
            rc = VBoxServiceControlReapThreads();
334
334
            if (RT_FAILURE(rc))
335
 
                VBoxServiceError("Control: Reaping stopped processes failed with rc=%Rrc\n", rc);
 
335
                VBoxServiceError("Reaping stopped processes failed with rc=%Rrc\n", rc);
336
336
            /* Keep going. */
337
337
 
338
338
            rc = VBoxServiceControlStartAllowed(&fStartAllowed);
353
353
    /* In case of an error we need to notify the host to not wait forever for our response. */
354
354
    if (RT_FAILURE(rc))
355
355
    {
356
 
        VBoxServiceError("Control: Starting process failed with rc=%Rrc\n", rc);
 
356
        VBoxServiceError("Starting process failed with rc=%Rrc\n", rc);
357
357
 
358
 
        int rc2 = VbglR3GuestCtrlExecReportStatus(uClientID, uContextID, 0 /* PID, invalid. */,
 
358
        /*
 
359
         * Note: The context ID can be 0 because we mabye weren't able to fetch the command
 
360
         *       from the host. The host in case has to deal with that!
 
361
         */
 
362
        int rc2 = VbglR3GuestCtrlExecReportStatus(uClientID, uContextID /* Might be 0 */, 0 /* PID, invalid */,
359
363
                                                  PROC_STS_ERROR, rc,
360
364
                                                  NULL /* pvData */, 0 /* cbData */);
361
365
        if (RT_FAILURE(rc2))
362
366
        {
363
 
            VBoxServiceError("Control: Error sending start process status to host, rc=%Rrc\n", rc2);
 
367
            VBoxServiceError("Error sending start process status to host, rc=%Rrc\n", rc2);
364
368
            if (RT_SUCCESS(rc))
365
369
                rc = rc2;
366
370
        }
444
448
    int rc = RTCritSectEnter(&g_csControlThreads);
445
449
    if (RT_SUCCESS(rc))
446
450
    {
447
 
        VBoxServiceVerbose(3, "Control: Setting thread (PID %u) inactive\n",
448
 
                           pThread->uPID);
 
451
        VBoxServiceVerbose(3, "Setting thread (PID %u) to list %d\n",
 
452
                           pThread->uPID, enmList);
449
453
 
450
454
        PRTLISTNODE pAnchor = NULL;
451
455
        switch (enmList)
562
566
                                                pabBuffer, cbMaxBufSize, &cbSize);
563
567
    if (RT_FAILURE(rc))
564
568
    {
565
 
        VBoxServiceError("Control: [PID %u]: Failed to retrieve exec input command! Error: %Rrc\n",
 
569
        VBoxServiceError("[PID %u]: Failed to retrieve exec input command! Error: %Rrc\n",
566
570
                         uPID, rc);
567
571
    }
568
572
    else if (cbSize > cbMaxBufSize)
569
573
    {
570
 
        VBoxServiceError("Control: [PID %u]: Too much input received! cbSize=%u, cbMaxBufSize=%u\n",
 
574
        VBoxServiceError("[PID %u]: Too much input received! cbSize=%u, cbMaxBufSize=%u\n",
571
575
                         uPID, cbSize, cbMaxBufSize);
572
576
        rc = VERR_INVALID_PARAMETER;
573
577
    }
580
584
        if (uFlags & INPUT_FLAG_EOF)
581
585
        {
582
586
            fPendingClose = true;
583
 
            VBoxServiceVerbose(4, "Control: [PID %u]: Got last input block of size %u ...\n",
 
587
            VBoxServiceVerbose(4, "[PID %u]: Got last input block of size %u ...\n",
584
588
                               uPID, cbSize);
585
589
        }
586
590
 
587
591
        rc = VBoxServiceControlSetInput(uPID, uContextID, fPendingClose, pabBuffer,
588
592
                                        cbSize, &cbWritten);
589
 
        VBoxServiceVerbose(4, "Control: [PID %u]: Written input, CID=%u, rc=%Rrc, uFlags=0x%x, fPendingClose=%d, cbSize=%u, cbWritten=%u\n",
 
593
        VBoxServiceVerbose(4, "[PID %u]: Written input, CID=%u, rc=%Rrc, uFlags=0x%x, fPendingClose=%d, cbSize=%u, cbWritten=%u\n",
590
594
                           uPID, uContextID, rc, uFlags, fPendingClose, cbSize, cbWritten);
591
595
        if (RT_SUCCESS(rc))
592
596
        {
593
 
            if (cbWritten || !cbSize) /* Did we write something or was there anything to write at all? */
594
 
            {
595
 
                uStatus = INPUT_STS_WRITTEN;
596
 
                uFlags = 0;
597
 
            }
 
597
            uStatus = INPUT_STS_WRITTEN;
 
598
            uFlags = 0; /* No flags at the moment. */
598
599
        }
599
600
        else
600
601
        {
618
619
    }
619
620
    Assert(uStatus > INPUT_STS_UNDEFINED);
620
621
 
621
 
    VBoxServiceVerbose(3, "Control: [PID %u]: Input processed, CID=%u, uStatus=%u, uFlags=0x%x, cbWritten=%u\n",
 
622
    VBoxServiceVerbose(3, "[PID %u]: Input processed, CID=%u, uStatus=%u, uFlags=0x%x, cbWritten=%u\n",
622
623
                       uPID, uContextID, uStatus, uFlags, cbWritten);
623
624
 
624
625
    /* Note: Since the context ID is unique the request *has* to be completed here,
628
629
                                           uStatus, uFlags, (uint32_t)cbWritten);
629
630
 
630
631
    if (RT_FAILURE(rc))
631
 
        VBoxServiceError("Control: [PID %u]: Failed to report input status! Error: %Rrc\n",
 
632
        VBoxServiceError("[PID %u]: Failed to report input status! Error: %Rrc\n",
632
633
                         uPID, rc);
633
634
    return rc;
634
635
}
658
659
            uint32_t cbRead = 0;
659
660
            rc = VBoxServiceControlExecGetOutput(uPID, uContextID, uHandleID, RT_INDEFINITE_WAIT /* Timeout */,
660
661
                                                 pBuf, _64K /* cbSize */, &cbRead);
661
 
            VBoxServiceVerbose(3, "Control: [PID %u]: Got output, rc=%Rrc, CID=%u, cbRead=%u, uHandle=%u, uFlags=%u\n",
 
662
            VBoxServiceVerbose(3, "[PID %u]: Got output, rc=%Rrc, CID=%u, cbRead=%u, uHandle=%u, uFlags=%u\n",
662
663
                               uPID, rc, uContextID, cbRead, uHandleID, uFlags);
663
664
 
664
665
#ifdef DEBUG
703
704
    }
704
705
 
705
706
    if (RT_FAILURE(rc))
706
 
        VBoxServiceError("Control: [PID %u]: Error handling output command! Error: %Rrc\n",
 
707
        VBoxServiceError("[PID %u]: Error handling output command! Error: %Rrc\n",
707
708
                         uPID, rc);
708
709
    return rc;
709
710
}
712
713
/** @copydoc VBOXSERVICE::pfnStop */
713
714
static DECLCALLBACK(void) VBoxServiceControlStop(void)
714
715
{
715
 
    VBoxServiceVerbose(3, "Control: Stopping ...\n");
 
716
    VBoxServiceVerbose(3, "Stopping ...\n");
716
717
 
717
718
    /** @todo Later, figure what to do if we're in RTProcWait(). It's a very
718
719
     *        annoying call since doesn't support timeouts in the posix world. */
725
726
     */
726
727
    if (g_uControlSvcClientID)
727
728
    {
728
 
        VBoxServiceVerbose(3, "Control: Cancelling pending waits (client ID=%u) ...\n",
 
729
        VBoxServiceVerbose(3, "Cancelling pending waits (client ID=%u) ...\n",
729
730
                           g_uControlSvcClientID);
730
731
 
731
732
        int rc = VbglR3GuestCtrlCancelPendingWaits(g_uControlSvcClientID);
732
733
        if (RT_FAILURE(rc))
733
 
            VBoxServiceError("Control: Cancelling pending waits failed; rc=%Rrc\n", rc);
 
734
            VBoxServiceError("Cancelling pending waits failed; rc=%Rrc\n", rc);
734
735
    }
735
736
}
736
737
 
751
752
        {
752
753
            PVBOXSERVICECTRLTHREAD pNext = RTListNodeGetNext(&pThread->Node, VBOXSERVICECTRLTHREAD, Node);
753
754
            bool fLast = RTListNodeIsLast(&g_lstControlThreadsInactive, &pThread->Node);
754
 
 
755
 
            int rc2 = VBoxServiceControlThreadWait(pThread, 30 * 1000 /* 30 seconds max. */);
 
755
            int rc2 = VBoxServiceControlThreadWait(pThread, 30 * 1000 /* 30 seconds max. */,
 
756
                                                   NULL /* rc */);
756
757
            if (RT_SUCCESS(rc2))
757
758
            {
758
759
                RTListNodeRemove(&pThread->Node);
760
761
                rc2 = VBoxServiceControlThreadFree(pThread);
761
762
                if (RT_FAILURE(rc2))
762
763
                {
763
 
                    VBoxServiceError("Control: Stopping guest process thread failed with rc=%Rrc\n", rc2);
 
764
                    VBoxServiceError("Freeing guest process thread failed with rc=%Rrc\n", rc2);
764
765
                    if (RT_SUCCESS(rc)) /* Keep original failure. */
765
766
                        rc = rc2;
766
767
                }
767
768
            }
768
769
            else
769
 
                VBoxServiceError("Control: Waiting on guest process thread failed with rc=%Rrc\n", rc2);
 
770
                VBoxServiceError("Waiting on guest process thread failed with rc=%Rrc\n", rc2);
770
771
            /* Keep going. */
771
772
 
772
773
            if (fLast)
780
781
            rc = rc2;
781
782
    }
782
783
 
783
 
    VBoxServiceVerbose(4, "Control: Reaping threads returned with rc=%Rrc\n", rc);
 
784
    VBoxServiceVerbose(4, "Reaping threads returned with rc=%Rrc\n", rc);
784
785
    return rc;
785
786
}
786
787
 
790
791
 */
791
792
static void VBoxServiceControlShutdown(void)
792
793
{
793
 
    VBoxServiceVerbose(2, "Control: Shutting down ...\n");
 
794
    VBoxServiceVerbose(2, "Shutting down ...\n");
794
795
 
795
796
    /* Signal all threads in the active list that we want to shutdown. */
796
797
    PVBOXSERVICECTRLTHREAD pThread;
805
806
        bool fLast = RTListNodeIsLast(&g_lstControlThreadsActive, &pThread->Node);
806
807
 
807
808
        int rc2 = VBoxServiceControlThreadWait(pThread,
808
 
                                               30 * 1000 /* Wait 30 seconds max. */);
 
809
                                               30 * 1000 /* Wait 30 seconds max. */,
 
810
                                               NULL /* rc */);
809
811
        if (RT_FAILURE(rc2))
810
 
            VBoxServiceError("Control: Guest process thread failed to stop; rc=%Rrc\n", rc2);
 
812
            VBoxServiceError("Guest process thread failed to stop; rc=%Rrc\n", rc2);
811
813
 
812
814
        if (fLast)
813
815
            break;
817
819
 
818
820
    int rc2 = VBoxServiceControlReapThreads();
819
821
    if (RT_FAILURE(rc2))
820
 
        VBoxServiceError("Control: Reaping inactive threads failed with rc=%Rrc\n", rc2);
 
822
        VBoxServiceError("Reaping inactive threads failed with rc=%Rrc\n", rc2);
821
823
 
822
824
    AssertMsg(RTListIsEmpty(&g_lstControlThreadsActive),
823
825
              ("Guest process active thread list still contains entries when it should not\n"));
827
829
    /* Destroy critical section. */
828
830
    RTCritSectDelete(&g_csControlThreads);
829
831
 
830
 
    VBoxServiceVerbose(2, "Control: Shutting down complete\n");
 
832
    VBoxServiceVerbose(2, "Shutting down complete\n");
831
833
}
832
834
 
833
835
 
834
836
/** @copydoc VBOXSERVICE::pfnTerm */
835
837
static DECLCALLBACK(void) VBoxServiceControlTerm(void)
836
838
{
837
 
    VBoxServiceVerbose(3, "Control: Terminating ...\n");
 
839
    VBoxServiceVerbose(3, "Terminating ...\n");
838
840
 
839
841
    VBoxServiceControlShutdown();
840
842
 
841
 
    VBoxServiceVerbose(3, "Control: Disconnecting client ID=%u ...\n",
 
843
    VBoxServiceVerbose(3, "Disconnecting client ID=%u ...\n",
842
844
                       g_uControlSvcClientID);
843
845
    VbglR3GuestCtrlDisconnect(g_uControlSvcClientID);
844
846
    g_uControlSvcClientID = 0;
878
880
            RTListForEach(&g_lstControlThreadsActive, pThread, VBOXSERVICECTRLTHREAD, Node)
879
881
                uProcsRunning++;
880
882
 
881
 
            VBoxServiceVerbose(3, "Control: Maximum served guest processes set to %u, running=%u\n",
 
883
            VBoxServiceVerbose(3, "Maximum served guest processes set to %u, running=%u\n",
882
884
                               g_uControlProcsMaxKept, uProcsRunning);
883
885
 
884
886
            int32_t iProcsLeft = (g_uControlProcsMaxKept - uProcsRunning - 1);
885
887
            if (iProcsLeft < 0)
886
888
            {
887
 
                VBoxServiceVerbose(3, "Control: Maximum running guest processes reached (%u)\n",
 
889
                VBoxServiceVerbose(3, "Maximum running guest processes reached (%u)\n",
888
890
                                   g_uControlProcsMaxKept);
889
891
                fLimitReached = true;
890
892
            }
978
980
                    Assert(pThreadCur != pThread); /* can't happen */
979
981
                    uint32_t uTriedPID = uPID;
980
982
                    uPID += 391939;
981
 
                    VBoxServiceVerbose(2, "ControlThread: PID %u was used before, trying again with %u ...\n",
 
983
                    VBoxServiceVerbose(2, "PID %u was used before, trying again with %u ...\n",
982
984
                                       uTriedPID, uPID);
983
985
                    fTryAgain = true;
984
986
                    break;