VirtualBox

Changeset 36331 in vbox


Ignore:
Timestamp:
Mar 21, 2011 7:17:12 PM (14 years ago)
Author:
vboxsync
Message:

VBoxService: Attempt to fix pre-init (broken by r70386). End VBoxService in the 'Terminated' or 'Failed' state, don't transition from 'Failed' to 'Terminated'. (untested)

Location:
trunk/src/VBox/Additions/common/VBoxService
Files:
4 edited

Legend:

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

    r35715 r36331  
    345345        }
    346346        else
     347        {
    347348            vboxServiceWinSetStatus(SERVICE_STOPPED, 0);
     349#if 0 /** @todo r=bird: Enable this if SERVICE_CONTROL_STOP isn't triggered automatically */
     350            VBoxServiceStopServices();
     351#endif
     352        }
    348353    }
    349354    /**@todo r=bird: else vboxServiceWinSetStatus(SERVICE_STOPPED, 0); ? */
  • trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp

    r36330 r36331  
    4040#include <iprt/buildconfig.h>
    4141#include <iprt/initterm.h>
     42#include <iprt/message.h>
    4243#include <iprt/path.h>
    4344#include <iprt/semaphore.h>
     
    7778    /** The worker thread. NIL_RTTHREAD if it's the main thread. */
    7879    RTTHREAD        Thread;
     80    /** Whether Pre-init was called. */
     81    bool            fPreInited;
    7982    /** Shutdown indicator. */
    8083    bool volatile   fShutdown;
     
    8891{
    8992#ifdef VBOXSERVICE_CONTROL
    90     { &g_Control,   NIL_RTTHREAD, false, false, false, true },
     93    { &g_Control,       NIL_RTTHREAD, false, false, false, false, true },
    9194#endif
    9295#ifdef VBOXSERVICE_TIMESYNC
    93     { &g_TimeSync,  NIL_RTTHREAD, false, false, false, true },
     96    { &g_TimeSync,      NIL_RTTHREAD, false, false, false, false, true },
    9497#endif
    9598#ifdef VBOXSERVICE_CLIPBOARD
    96     { &g_Clipboard, NIL_RTTHREAD, false, false, false, true },
     99    { &g_Clipboard,     NIL_RTTHREAD, false, false, false, false, true },
    97100#endif
    98101#ifdef VBOXSERVICE_VMINFO
    99     { &g_VMInfo,    NIL_RTTHREAD, false, false, false, true },
     102    { &g_VMInfo,        NIL_RTTHREAD, false, false, false, false, true },
    100103#endif
    101104#ifdef VBOXSERVICE_CPUHOTPLUG
    102     { &g_CpuHotPlug, NIL_RTTHREAD, false, false, false, true },
     105    { &g_CpuHotPlug,    NIL_RTTHREAD, false, false, false, false, true },
    103106#endif
    104107#ifdef VBOXSERVICE_MANAGEMENT
    105108# ifdef VBOX_WITH_MEMBALLOON
    106     { &g_MemBalloon, NIL_RTTHREAD, false, false, false, true },
     109    { &g_MemBalloon,    NIL_RTTHREAD, false, false, false, false, true },
    107110# endif
    108     { &g_VMStatistics, NIL_RTTHREAD, false, false, false, true },
     111    { &g_VMStatistics,  NIL_RTTHREAD, false, false, false, false, true },
    109112#endif
    110113#if defined(VBOX_WITH_PAGE_SHARING) && defined(RT_OS_WINDOWS)
    111     { &g_PageSharing, NIL_RTTHREAD, false, false, false, true },
     114    { &g_PageSharing,   NIL_RTTHREAD, false, false, false, false, true },
    112115#endif
    113116#ifdef VBOX_WITH_SHARED_FOLDERS
    114     { &g_AutoMount, NIL_RTTHREAD, false, false, false, true },
     117    { &g_AutoMount,     NIL_RTTHREAD, false, false, false, false, true },
    115118#endif
    116119};
     
    232235 * Reports the current VBoxService status to the host.
    233236 *
     237 * This makes sure that the Failed state is sticky.
     238 *
    234239 * @return  IPRT status code.
    235240 * @param   enmStatus               Status to report to the host.
     
    237242int VBoxServiceReportStatus(VBoxGuestFacilityStatus enmStatus)
    238243{
    239     /* Report the host that we're up and running! */
    240     int rc = VbglR3ReportAdditionsStatus(VBoxGuestFacilityType_VBoxService,
    241                                          enmStatus, 0 /* Flags */);
    242     if (RT_FAILURE(rc))
    243         VBoxServiceError("Could not report VBoxService status (%u), rc=%Rrc\n", enmStatus, rc);
    244     return rc;
     244    /*
     245     * VBoxGuestFacilityStatus_Failed is sticky.
     246     */
     247    static VBoxGuestFacilityStatus s_enmLastStatus = VBoxGuestFacilityStatus_Inactive;
     248    if (s_enmLastStatus != VBoxGuestFacilityStatus_Failed)
     249    {
     250        int rc = VbglR3ReportAdditionsStatus(VBoxGuestFacilityType_VBoxService,
     251                                             enmStatus, 0 /* Flags */);
     252        if (RT_FAILURE(rc))
     253        {
     254            VBoxServiceError("Could not report VBoxService status (%u), rc=%Rrc\n", enmStatus, rc);
     255            return rc;
     256        }
     257        s_enmLastStatus = enmStatus;
     258    }
     259    return VINF_SUCCESS;
    245260}
    246261
     
    304319    RTThreadUserSignal(ThreadSelf);
    305320    return rc;
     321}
     322
     323
     324/**
     325 * Lazily calls the pfnPreInit method on each service.
     326 *
     327 * @returns VBox status code, error message displayed.
     328 */
     329static RTEXITCODE vboxServiceLazyPreInit(void)
     330{
     331    for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
     332        if (!g_aServices[j].fPreInited)
     333        {
     334            int rc = g_aServices[j].pDesc->pfnPreInit();
     335            if (RT_FAILURE(rc))
     336                return VBoxServiceError("Service '%s' failed pre-init: %Rrc\n", g_aServices[j].pDesc->pszName, rc);
     337            g_aServices[j].fPreInited = true;
     338        }
     339    return RTEXITCODE_SUCCESS;
    306340}
    307341
     
    344378                    VBoxServiceError("Service '%s' failed to initialize: %Rrc\n",
    345379                                     g_aServices[j].pDesc->pszName, rc);
     380                    VBoxServiceReportStatus(VBoxGuestFacilityStatus_Failed);
    346381                    return rc;
    347382                }
     
    373408        g_aServices[j].fStarted = true;
    374409
    375         /* Wait for the thread to initialize.
    376          *
    377          * @todo There is a race between waiting and checking
    378          *       the fShutdown flag of a thread here and processing
    379          *       the thread's actual worker loop. If the thread decides
    380          *       to exit the loop before we skipped the fShutdown check
    381          *       below the service will fail to start! */
     410        /* Wait for the thread to initialize. */
     411        /** @todo There is a race between waiting and checking
     412         * the fShutdown flag of a thread here and processing
     413         * the thread's actual worker loop. If the thread decides
     414         * to exit the loop before we skipped the fShutdown check
     415         * below the service will fail to start! */
    382416        RTThreadUserWait(g_aServices[j].Thread, 60 * 1000);
    383417        if (g_aServices[j].fShutdown)
     
    407441int VBoxServiceStopServices(void)
    408442{
    409     int rc = VINF_SUCCESS;
    410 
    411443    VBoxServiceReportStatus(VBoxGuestFacilityStatus_Terminating);
    412444
     
    430462     * Wait for all the service threads to complete.
    431463     */
     464    int rc = VINF_SUCCESS;
    432465    for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
    433466    {
     
    437470        {
    438471            VBoxServiceVerbose(2, "Waiting for service '%s' to stop ...\n", g_aServices[j].pDesc->pszName);
     472            int rc2 = VINF_SUCCESS;
    439473            for (int i = 0; i < 30; i++) /* Wait 30 seconds in total */
    440474            {
    441                 rc = RTThreadWait(g_aServices[j].Thread, 1000 /* Wait 1 second */, NULL);
    442                 if (RT_SUCCESS(rc))
     475                rc2 = RTThreadWait(g_aServices[j].Thread, 1000 /* Wait 1 second */, NULL);
     476                if (RT_SUCCESS(rc2))
    443477                    break;
    444478#ifdef RT_OS_WINDOWS
     
    447481#endif
    448482            }
    449             if (RT_FAILURE(rc))
    450                 VBoxServiceError("Service '%s' failed to stop. (%Rrc)\n", g_aServices[j].pDesc->pszName, rc);
     483            if (RT_FAILURE(rc2))
     484            {
     485                VBoxServiceError("Service '%s' failed to stop. (%Rrc)\n", g_aServices[j].pDesc->pszName, rc2);
     486                rc = rc2;
     487            }
    451488        }
    452489        VBoxServiceVerbose(3, "Terminating service '%s' (%d) ...\n", g_aServices[j].pDesc->pszName, j);
     
    459496     * sleeping in VBoxServiceMainWait).
    460497     */
     498    ASMAtomicWriteBool(&g_fWindowsServiceShutdown, true);
    461499    if (g_hEvtWindowsService != NIL_RTSEMEVENT)
    462500    {
    463501        VBoxServiceVerbose(3, "Stopping the main thread...\n");
    464         ASMAtomicWriteBool(&g_fWindowsServiceShutdown, true);
    465         rc = RTSemEventSignal(g_hEvtWindowsService);
    466         AssertRC(rc);
    467     }
    468 #endif
    469 
    470     VBoxServiceVerbose(2, "Stopping services returned: rc=%Rrc\n", rc);
    471     VBoxServiceReportStatus(RT_SUCCESS(rc)
    472                             ? VBoxGuestFacilityStatus_Paused : VBoxGuestFacilityStatus_Failed);
     502        int rc2 = RTSemEventSignal(g_hEvtWindowsService);
     503        AssertRC(rc2);
     504    }
     505#endif
     506
     507    VBoxServiceVerbose(2, "Stopping services returning: %Rrc\n", rc);
     508    VBoxServiceReportStatus(RT_SUCCESS(rc) ? VBoxGuestFacilityStatus_Paused : VBoxGuestFacilityStatus_Failed);
    473509    return rc;
    474510}
     
    535571int main(int argc, char **argv)
    536572{
     573    RTEXITCODE rcExit;
     574
    537575    /*
    538576     * Init globals and such.
    539577     */
    540     RTR3Init();
    541 
     578    int rc = RTR3Init();
     579    if (RT_FAILURE(rc))
     580        return RTMsgInitFailure(rc);
    542581    g_pszProgName = RTPathFilename(argv[0]);
    543582
    544     int rc;
    545583#ifdef VBOXSERVICE_TOOLBOX
     584    /*
     585     * Run toolbox code before all other stuff since these things are simpler
     586     * shell/file/text utility like programs that just happens to be inside
     587     * VBoxService and shouldn't be subject to /dev/vboxguest, pid-files and
     588     * global mutex restrictions.
     589     */
     590# if 0 /** @todo r=bird: pending argv[0] bugfixing.  */
     591    if (VBoxServiceToolboxMain(argc, argv, &rcExit))
     592        return rcExit;
     593# else
    546594    if (argc > 1)
    547     {
    548         /*
    549          * Run toolbox code before all other stuff, especially before checking the global
    550          * mutex because VBoxService might spawn itself to execute some commands.
    551          */
    552         int iExitCode;
    553         if (VBoxServiceToolboxMain(argc - 1, &argv[1], &iExitCode))
    554             return iExitCode;
    555     }
     595        if (VBoxServiceToolboxMain(argc - 1, &argv[1], &rcExit))
     596            return rcExit;
     597# endif
    556598#endif
    557599
     
    567609    {
    568610        if (rc == VERR_ACCESS_DENIED)
    569             return VBoxServiceError("Not enough rights to start %s! Please start with Administrator/root privileges!\n",
     611            return VBoxServiceError("Insufficient privileges to start %s! Please start with Administrator/root privileges!\n",
    570612                                    g_pszProgName);
    571         else
    572             return VBoxServiceError("VbglR3Init failed with rc=%Rrc.\n", rc);
     613        return VBoxServiceError("VbglR3Init failed with rc=%Rrc.\n", rc);
    573614    }
    574615
     
    584625
    585626    /*
    586      * Parse the arguments                                       .
    587      *                                                           .
     627     * Parse the arguments.
     628     *
    588629     * Note! This code predates RTGetOpt, thus the manual parsing.
    589630     */
     
    640681
    641682                if (!fFound)
     683                {
     684                    rcExit = vboxServiceLazyPreInit();
     685                    if (rcExit != RTEXITCODE_SUCCESS)
     686                        return rcExit;
     687
    642688                    for (unsigned j = 0; !fFound && j < RT_ELEMENTS(g_aServices); j++)
    643689                    {
     
    649695                            return rc;
    650696                    }
     697                }
    651698                if (!fFound)
    652699                    return VBoxServiceSyntax("Unknown option '%s'\n", argv[i]);
     
    695742                default:
    696743                {
     744                    rcExit = vboxServiceLazyPreInit();
     745                    if (rcExit != RTEXITCODE_SUCCESS)
     746                        return rcExit;
     747
    697748                    bool fFound = false;
    698749                    for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
    699750                    {
    700                         rc = g_aServices[j].pDesc->pfnPreInit();
    701                         if (RT_FAILURE(rc))
    702                             return VBoxServiceError("Service '%s' failed pre-init: %Rrc\n", g_aServices[j].pDesc->pszName, rc);
    703                         else
    704                             rc = g_aServices[j].pDesc->pfnOption(&psz, argc, argv, &i);
     751                        rc = g_aServices[j].pDesc->pfnOption(&psz, argc, argv, &i);
    705752                        fFound = rc == VINF_SUCCESS;
    706753                        if (fFound)
     
    721768        return VBoxServiceSyntax("At least one service must be enabled.\n");
    722769
     770    /* Call pre-init if we didn't do it already. */
     771    rcExit = vboxServiceLazyPreInit();
     772    if (rcExit != RTEXITCODE_SUCCESS)
     773        return rcExit;
     774
    723775#ifdef RT_OS_WINDOWS
    724776    /*
     
    764816     * Daemonize if requested.
    765817     */
    766     RTEXITCODE rcExit;
    767818    if (fDaemonize && !fDaemonized)
    768819    {
     
    782833#endif
    783834    {
    784         VBoxServiceReportStatus(VBoxGuestFacilityStatus_PreInit);
    785 
    786835        /*
    787836         * Windows: We're running the service as a console application now. Start the
     
    797846            VBoxServiceMainWait();
    798847        VBoxServiceStopServices();
    799 
    800         /* Only report the "terminated" status when we really did run the internal services --
    801          * otherwise we also wrongly would report "terminated" when a user simply
    802          * wants to query the version or the command line help. */
    803         VBoxServiceReportStatus(VBoxGuestFacilityStatus_Terminated);
    804     }
     848    }
     849    VBoxServiceReportStatus(VBoxGuestFacilityStatus_Terminated);
    805850
    806851#ifdef RT_OS_WINDOWS
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r36330 r36331  
    286286
    287287#ifdef VBOXSERVICE_TOOLBOX
    288 extern bool         VBoxServiceToolboxMain(int argc, char **argv, int *piExitCode);
     288extern bool         VBoxServiceToolboxMain(int argc, char **argv, RTEXITCODE *prcExit);
    289289#endif
    290290
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp

    r36305 r36331  
    210210 * @param   argv                    Pointer to argument array.
    211211 */
    212 static int VBoxServiceToolboxMkDir(int argc, char **argv)
     212static RTEXITCODE VBoxServiceToolboxMkDir(int argc, char **argv)
    213213{
    214214     static const RTGETOPTDEF s_aOptions[] =
     
    332332 * @param   argv                    Pointer to argument array.
    333333 */
    334 static int VBoxServiceToolboxCat(int argc, char **argv)
     334static RTEXITCODE VBoxServiceToolboxCat(int argc, char **argv)
    335335{
    336336     static const RTGETOPTDEF s_aOptions[] =
     
    486486 * @param   argc                    Number of arguments.
    487487 * @param   argv                    Pointer to argument array.
    488  * @param   piExitCode              Pointer to receive exit code when internal command
    489  *                                  was handled.
    490  */
    491 bool VBoxServiceToolboxMain(int argc, char **argv, int *piExitCode)
     488 * @param   prcExit                 Where to store the exit code when an
     489 *                                  internal toolbox command was handled.
     490 */
     491bool VBoxServiceToolboxMain(int argc, char **argv, RTEXITCODE *prcExit)
    492492{
    493493    if (argc > 0) /* Do we have at least a main command? */
     
    496496            || !strcmp(argv[0], "vbox_cat"))
    497497        {
    498             *piExitCode = VBoxServiceToolboxCat(argc, argv);
     498            *prcExit = VBoxServiceToolboxCat(argc, argv);
    499499            return true;
    500500        }
    501         else if (   !strcmp(argv[0], "mkdir")
    502                  || !strcmp(argv[0], "vbox_mkdir"))
     501
     502        if (   !strcmp(argv[0], "mkdir")
     503            || !strcmp(argv[0], "vbox_mkdir"))
    503504        {
    504             *piExitCode = VBoxServiceToolboxMkDir(argc, argv);
     505            *prcExit = VBoxServiceToolboxMkDir(argc, argv);
    505506            return true;
    506507        }
Note: See TracChangeset for help on using the changeset viewer.

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