VirtualBox

Changeset 36466 in vbox


Ignore:
Timestamp:
Mar 29, 2011 5:40:35 PM (14 years ago)
Author:
vboxsync
Message:

Main/src-server/xpcom: Avoid initializing static variables with a constructor. Unsafe c++, and gcc on freebsd choked on it when optimizing. Who knows which gcc version will be next.

Location:
trunk/src/VBox/Main
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/Makefile.kmk

    r35967 r36466  
    245245
    246246VBoxSVC_CXXFLAGS = $(filter-out -Wno-unused,$(TEMPLATE_VBOXMAINEXE_CXXFLAGS))
    247 ## @todo We're disabling optimizations on FreeBSD to work around strange linker
    248 #        errors in release builds. Figure out why and how to work around it in a
    249 #        more optimal fashion.
    250 VBoxSVC_CXXFLAGS.freebsd = -O0
    251247
    252248VBoxSVC_INCS = \
  • trunk/src/VBox/Main/src-server/xpcom/server.cpp

    r35976 r36466  
    615615////////////////////////////////////////////////////////////////////////////////
    616616
    617 typedef NSFactoryDestructorProcPtr NSFactoryConsructorProcPtr;
     617typedef NSFactoryDestructorProcPtr NSFactoryConstructorProcPtr;
    618618
    619619/**
     
    621621 *
    622622 *  nsModuleComponentInfo lacks the factory construction callback, here we add
    623  *  it. This callback is called by NS_NewGenericFactoryEx() after a
    624  *  nsGenericFactory instance is successfully created.
     623 *  it. This callback is called straight after a nsGenericFactory instance is
     624 *  successfully created in RegisterSelfComponents.
    625625 */
    626 struct nsModuleComponentInfoEx : nsModuleComponentInfo
     626struct nsModuleComponentInfoPlusFactoryConstructor
    627627{
    628     nsModuleComponentInfoEx() {}
    629     nsModuleComponentInfoEx(int) {}
    630 
    631     nsModuleComponentInfoEx(
    632         const char*                                 aDescription,
    633         const nsCID&                                aCID,
    634         const char*                                 aContractID,
    635         NSConstructorProcPtr                        aConstructor,
    636         NSRegisterSelfProcPtr                       aRegisterSelfProc,
    637         NSUnregisterSelfProcPtr                     aUnregisterSelfProc,
    638         NSFactoryDestructorProcPtr                  aFactoryDestructor,
    639         NSGetInterfacesProcPtr                      aGetInterfacesProc,
    640         NSGetLanguageHelperProcPtr                  aGetLanguageHelperProc,
    641         nsIClassInfo **                             aClassInfoGlobal,
    642         PRUint32                                    aFlags,
    643         NSFactoryConsructorProcPtr                  aFactoryConstructor)
    644     {
    645         mDescription = aDescription;
    646         mCID = aCID;
    647         mContractID = aContractID;
    648         mConstructor = aConstructor;
    649         mRegisterSelfProc = aRegisterSelfProc;
    650         mUnregisterSelfProc = aUnregisterSelfProc;
    651         mFactoryDestructor = aFactoryDestructor;
    652         mGetInterfacesProc = aGetInterfacesProc;
    653         mGetLanguageHelperProc = aGetLanguageHelperProc;
    654         mClassInfoGlobal = aClassInfoGlobal;
    655         mFlags = aFlags;
    656         mFactoryConstructor = aFactoryConstructor;
    657     }
    658 
     628    /** standard module component information */
     629    const nsModuleComponentInfo *mpModuleComponentInfo;
    659630    /** (optional) Factory Construction Callback */
    660     NSFactoryConsructorProcPtr mFactoryConstructor;
     631    NSFactoryConstructorProcPtr mFactoryConstructor;
    661632};
    662633
    663 ////////////////////////////////////////////////////////////////////////////////
    664 
    665 static const nsModuleComponentInfoEx components[] =
     634/////////////////////////////////////////////////////////////////////////////
     635
     636/**
     637 * Helper function to register self components upon start-up
     638 * of the out-of-proc server.
     639 */
     640static nsresult
     641RegisterSelfComponents(nsIComponentRegistrar *registrar,
     642                       const nsModuleComponentInfoPlusFactoryConstructor *aComponents,
     643                       PRUint32 count)
    666644{
    667     nsModuleComponentInfoEx(
     645    nsresult rc = NS_OK;
     646    const nsModuleComponentInfoPlusFactoryConstructor *info = aComponents;
     647    for (PRUint32 i = 0; i < count && NS_SUCCEEDED(rc); i++, info++)
     648    {
     649        /* skip components w/o a constructor */
     650        if (!info->mpModuleComponentInfo->mConstructor)
     651            continue;
     652        /* create a new generic factory for a component and register it */
     653        nsIGenericFactory *factory;
     654        rc = NS_NewGenericFactory(&factory, info->mpModuleComponentInfo);
     655        if (NS_SUCCEEDED(rc) && info->mFactoryConstructor)
     656        {
     657            rc = info->mFactoryConstructor();
     658            if (NS_FAILED(rc))
     659                NS_RELEASE(factory);
     660        }
     661        if (NS_SUCCEEDED(rc))
     662        {
     663            rc = registrar->RegisterFactory(info->mpModuleComponentInfo->mCID,
     664                                            info->mpModuleComponentInfo->mDescription,
     665                                            info->mpModuleComponentInfo->mContractID,
     666                                            factory);
     667            NS_RELEASE(factory);
     668        }
     669    }
     670    return rc;
     671}
     672
     673/////////////////////////////////////////////////////////////////////////////
     674
     675static ipcIService *gIpcServ = nsnull;
     676static const char *g_pszPidFile = NULL;
     677
     678class ForceQuitEvent : public MyEvent
     679{
     680    void *handler()
     681    {
     682        LogFlowFunc(("\n"));
     683
     684        gKeepRunning = PR_FALSE;
     685
     686        if (g_pszPidFile)
     687            RTFileDelete(g_pszPidFile);
     688
     689        return NULL;
     690    }
     691};
     692
     693static void signal_handler(int sig)
     694{
     695    if (gEventQ && gKeepRunning)
     696    {
     697        if (sig == SIGUSR1)
     698        {
     699            if (gAllowSigUsrQuit)
     700            {
     701                VirtualBoxClassFactory::MaybeQuitEvent *ev = new VirtualBoxClassFactory::MaybeQuitEvent();
     702                ev->postTo(gEventQ);
     703            }
     704            /* else do nothing */
     705        }
     706        else
     707        {
     708            /* post a force quit event to the queue */
     709            ForceQuitEvent *ev = new ForceQuitEvent();
     710            ev->postTo(gEventQ);
     711        }
     712    }
     713}
     714
     715static nsresult vboxsvcSpawnDaemonByReExec(const char *pszPath)
     716{
     717    PRFileDesc *readable = nsnull, *writable = nsnull;
     718    PRProcessAttr *attr = nsnull;
     719    nsresult rv = NS_ERROR_FAILURE;
     720    PRFileDesc *devNull;
     721    // The ugly casts are necessary because the PR_CreateProcessDetached has
     722    // a const array of writable strings as a parameter. It won't write. */
     723    char * const args[] = { (char *)pszPath, (char *)"--auto-shutdown", 0 };
     724
     725    // Use a pipe to determine when the daemon process is in the position
     726    // to actually process requests. The daemon will write "READY" to the pipe.
     727    if (PR_CreatePipe(&readable, &writable) != PR_SUCCESS)
     728        goto end;
     729    PR_SetFDInheritable(writable, PR_TRUE);
     730
     731    attr = PR_NewProcessAttr();
     732    if (!attr)
     733        goto end;
     734
     735    if (PR_ProcessAttrSetInheritableFD(attr, writable, VBOXSVC_STARTUP_PIPE_NAME) != PR_SUCCESS)
     736        goto end;
     737
     738    devNull = PR_Open("/dev/null", PR_RDWR, 0);
     739    if (!devNull)
     740        goto end;
     741
     742    PR_ProcessAttrSetStdioRedirect(attr, PR_StandardInput, devNull);
     743    PR_ProcessAttrSetStdioRedirect(attr, PR_StandardOutput, devNull);
     744    PR_ProcessAttrSetStdioRedirect(attr, PR_StandardError, devNull);
     745
     746    if (PR_CreateProcessDetached(pszPath, args, nsnull, attr) != PR_SUCCESS)
     747        goto end;
     748
     749    // Close /dev/null
     750    PR_Close(devNull);
     751    // Close the child end of the pipe to make it the only owner of the
     752    // file descriptor, so that unexpected closing can be detected.
     753    PR_Close(writable);
     754    writable = nsnull;
     755
     756    char msg[10];
     757    memset(msg, '\0', sizeof(msg));
     758    if (   PR_Read(readable, msg, sizeof(msg)-1) != 5
     759        || strcmp(msg, "READY"))
     760        goto end;
     761
     762    rv = NS_OK;
     763
     764end:
     765    if (readable)
     766        PR_Close(readable);
     767    if (writable)
     768        PR_Close(writable);
     769    if (attr)
     770        PR_DestroyProcessAttr(attr);
     771    return rv;
     772}
     773
     774int main(int argc, char **argv)
     775{
     776    /*
     777     * Initialize the VBox runtime without loading
     778     * the support driver
     779     */
     780    RTR3Init();
     781
     782    static const RTGETOPTDEF s_aOptions[] =
     783    {
     784        { "--automate",       'a', RTGETOPT_REQ_NOTHING },
     785        { "--auto-shutdown",  'A', RTGETOPT_REQ_NOTHING },
     786        { "--daemonize",      'd', RTGETOPT_REQ_NOTHING },
     787        { "--pidfile",        'p', RTGETOPT_REQ_STRING  },
     788    };
     789
     790    bool            fDaemonize = false;
     791    PRFileDesc      *daemon_pipe_wr = nsnull;
     792
     793    RTGETOPTSTATE   GetOptState;
     794    int vrc = RTGetOptInit(&GetOptState, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, 0 /*fFlags*/);
     795    AssertRC(vrc);
     796
     797    RTGETOPTUNION   ValueUnion;
     798    while ((vrc = RTGetOpt(&GetOptState, &ValueUnion)))
     799    {
     800        switch (vrc)
     801        {
     802            case 'a':
     803            {
     804                /* --automate mode means we are started by XPCOM on
     805                 * demand. Daemonize ourselves and activate
     806                 * auto-shutdown. */
     807                gAutoShutdown = true;
     808                fDaemonize = true;
     809                break;
     810            }
     811
     812            /* Used together with '-P', see below. Internal use only. */
     813            case 'A':
     814            {
     815                gAutoShutdown = true;
     816                break;
     817            }
     818
     819            case 'd':
     820            {
     821                fDaemonize = true;
     822                break;
     823            }
     824
     825            case 'p':
     826            {
     827                g_pszPidFile = ValueUnion.psz;
     828                break;
     829            }
     830
     831            case 'h':
     832            {
     833                RTPrintf("no help\n");
     834                return 1;
     835            }
     836
     837            case 'V':
     838            {
     839                RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
     840                return 0;
     841            }
     842
     843            default:
     844                return RTGetOptPrintError(vrc, &ValueUnion);
     845        }
     846    }
     847
     848    if (fDaemonize)
     849    {
     850        vboxsvcSpawnDaemonByReExec(argv[0]);
     851        exit(126);
     852    }
     853
     854    nsresult    rc;
     855
     856    daemon_pipe_wr = PR_GetInheritedFD(VBOXSVC_STARTUP_PIPE_NAME);
     857    RTEnvUnset("NSPR_INHERIT_FDS");
     858
     859    const nsModuleComponentInfo VirtualBoxInfo = {
    668860        "VirtualBox component",
    669861        CLSID_VirtualBox,
     
    676868        NULL, // language helper
    677869        &NS_CLASSINFO_NAME(VirtualBox),
    678         0, // flags
    679         VirtualBoxClassFactory::FactoryConstructor // factory constructor function
    680     )
    681 };
    682 
    683 /////////////////////////////////////////////////////////////////////////////
    684 
    685 /**
    686  *  Extends NS_NewGenericFactory() by immediately calling
    687  *  nsModuleComponentInfoEx::mFactoryConstructor before returning to the
    688  *  caller.
    689  */
    690 nsresult
    691 NS_NewGenericFactoryEx(nsIGenericFactory **result,
    692                        const nsModuleComponentInfoEx *info)
    693 {
    694     AssertReturn(result, NS_ERROR_INVALID_POINTER);
    695 
    696     nsresult rv = NS_NewGenericFactory(result, info);
    697     if (NS_SUCCEEDED(rv) && info && info->mFactoryConstructor)
    698     {
    699         rv = info->mFactoryConstructor();
    700         if (NS_FAILED(rv))
    701             NS_RELEASE(*result);
    702     }
    703 
    704     return rv;
    705 }
    706 
    707 /////////////////////////////////////////////////////////////////////////////
    708 
    709 /**
    710  * Helper function to register self components upon start-up
    711  * of the out-of-proc server.
    712  */
    713 static nsresult
    714 RegisterSelfComponents(nsIComponentRegistrar *registrar,
    715                        const nsModuleComponentInfoEx *aComponents,
    716                        PRUint32 count)
    717 {
    718     nsresult rc = NS_OK;
    719     const nsModuleComponentInfoEx *info = aComponents;
    720     for (PRUint32 i = 0; i < count && NS_SUCCEEDED(rc); i++, info++)
    721     {
    722         /* skip components w/o a constructor */
    723         if (!info->mConstructor)
    724             continue;
    725         /* create a new generic factory for a component and register it */
    726         nsIGenericFactory *factory;
    727         rc = NS_NewGenericFactoryEx(&factory, info);
    728         if (NS_SUCCEEDED(rc))
    729         {
    730             rc = registrar->RegisterFactory(info->mCID,
    731                                             info->mDescription,
    732                                             info->mContractID,
    733                                             factory);
    734             factory->Release();
    735         }
    736     }
    737     return rc;
    738 }
    739 
    740 /////////////////////////////////////////////////////////////////////////////
    741 
    742 static ipcIService *gIpcServ = nsnull;
    743 static const char *g_pszPidFile = NULL;
    744 
    745 class ForceQuitEvent : public MyEvent
    746 {
    747     void *handler()
    748     {
    749         LogFlowFunc(("\n"));
    750 
    751         gKeepRunning = PR_FALSE;
    752 
    753         if (g_pszPidFile)
    754             RTFileDelete(g_pszPidFile);
    755 
    756         return NULL;
    757     }
    758 };
    759 
    760 static void signal_handler(int sig)
    761 {
    762     if (gEventQ && gKeepRunning)
    763     {
    764         if (sig == SIGUSR1)
    765         {
    766             if (gAllowSigUsrQuit)
    767             {
    768                 VirtualBoxClassFactory::MaybeQuitEvent *ev = new VirtualBoxClassFactory::MaybeQuitEvent();
    769                 ev->postTo(gEventQ);
    770             }
    771             /* else do nothing */
    772         }
    773         else
    774         {
    775             /* post a force quit event to the queue */
    776             ForceQuitEvent *ev = new ForceQuitEvent();
    777             ev->postTo(gEventQ);
    778         }
    779     }
    780 }
    781 
    782 static nsresult vboxsvcSpawnDaemonByReExec(const char *pszPath)
    783 {
    784     PRFileDesc *readable = nsnull, *writable = nsnull;
    785     PRProcessAttr *attr = nsnull;
    786     nsresult rv = NS_ERROR_FAILURE;
    787     PRFileDesc *devNull;
    788     // The ugly casts are necessary because the PR_CreateProcessDetached has
    789     // a const array of writable strings as a parameter. It won't write. */
    790     char * const args[] = { (char *)pszPath, (char *)"--auto-shutdown", 0 };
    791 
    792     // Use a pipe to determine when the daemon process is in the position
    793     // to actually process requests. The daemon will write "READY" to the pipe.
    794     if (PR_CreatePipe(&readable, &writable) != PR_SUCCESS)
    795         goto end;
    796     PR_SetFDInheritable(writable, PR_TRUE);
    797 
    798     attr = PR_NewProcessAttr();
    799     if (!attr)
    800         goto end;
    801 
    802     if (PR_ProcessAttrSetInheritableFD(attr, writable, VBOXSVC_STARTUP_PIPE_NAME) != PR_SUCCESS)
    803         goto end;
    804 
    805     devNull = PR_Open("/dev/null", PR_RDWR, 0);
    806     if (!devNull)
    807         goto end;
    808 
    809     PR_ProcessAttrSetStdioRedirect(attr, PR_StandardInput, devNull);
    810     PR_ProcessAttrSetStdioRedirect(attr, PR_StandardOutput, devNull);
    811     PR_ProcessAttrSetStdioRedirect(attr, PR_StandardError, devNull);
    812 
    813     if (PR_CreateProcessDetached(pszPath, args, nsnull, attr) != PR_SUCCESS)
    814         goto end;
    815 
    816     // Close /dev/null
    817     PR_Close(devNull);
    818     // Close the child end of the pipe to make it the only owner of the
    819     // file descriptor, so that unexpected closing can be detected.
    820     PR_Close(writable);
    821     writable = nsnull;
    822 
    823     char msg[10];
    824     memset(msg, '\0', sizeof(msg));
    825     if (   PR_Read(readable, msg, sizeof(msg)-1) != 5
    826         || strcmp(msg, "READY"))
    827         goto end;
    828 
    829     rv = NS_OK;
    830 
    831 end:
    832     if (readable)
    833         PR_Close(readable);
    834     if (writable)
    835         PR_Close(writable);
    836     if (attr)
    837         PR_DestroyProcessAttr(attr);
    838     return rv;
    839 }
    840 
    841 int main(int argc, char **argv)
    842 {
    843     /*
    844      * Initialize the VBox runtime without loading
    845      * the support driver
    846      */
    847     RTR3Init();
    848 
    849     static const RTGETOPTDEF s_aOptions[] =
    850     {
    851         { "--automate",       'a', RTGETOPT_REQ_NOTHING },
    852         { "--auto-shutdown",  'A', RTGETOPT_REQ_NOTHING },
    853         { "--daemonize",      'd', RTGETOPT_REQ_NOTHING },
    854         { "--pidfile",        'p', RTGETOPT_REQ_STRING  },
     870        0 // flags
    855871    };
    856872
    857     bool            fDaemonize = false;
    858     PRFileDesc      *daemon_pipe_wr = nsnull;
    859 
    860     RTGETOPTSTATE   GetOptState;
    861     int vrc = RTGetOptInit(&GetOptState, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, 0 /*fFlags*/);
    862     AssertRC(vrc);
    863 
    864     RTGETOPTUNION   ValueUnion;
    865     while ((vrc = RTGetOpt(&GetOptState, &ValueUnion)))
    866     {
    867         switch (vrc)
    868         {
    869             case 'a':
    870             {
    871                 /* --automate mode means we are started by XPCOM on
    872                  * demand. Daemonize ourselves and activate
    873                  * auto-shutdown. */
    874                 gAutoShutdown = true;
    875                 fDaemonize = true;
    876                 break;
    877             }
    878 
    879             /* Used together with '-P', see below. Internal use only. */
    880             case 'A':
    881             {
    882                 gAutoShutdown = true;
    883                 break;
    884             }
    885 
    886             case 'd':
    887             {
    888                 fDaemonize = true;
    889                 break;
    890             }
    891 
    892             case 'p':
    893             {
    894                 g_pszPidFile = ValueUnion.psz;
    895                 break;
    896             }
    897 
    898             case 'h':
    899             {
    900                 RTPrintf("no help\n");
    901                 return 1;
    902             }
    903 
    904             case 'V':
    905             {
    906                 RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
    907                 return 0;
    908             }
    909 
    910             default:
    911                 return RTGetOptPrintError(vrc, &ValueUnion);
    912         }
    913     }
    914 
    915     if (fDaemonize)
    916     {
    917         vboxsvcSpawnDaemonByReExec(argv[0]);
    918         exit(126);
    919     }
    920 
    921     nsresult    rc;
    922 
    923     daemon_pipe_wr = PR_GetInheritedFD(VBOXSVC_STARTUP_PIPE_NAME);
    924     RTEnvUnset("NSPR_INHERIT_FDS");
     873    const nsModuleComponentInfoPlusFactoryConstructor components[] = {
     874        {
     875            &VirtualBoxInfo,
     876            VirtualBoxClassFactory::FactoryConstructor // factory constructor function
     877        }
     878    };
    925879
    926880    do
     
    943897        registrar->AutoRegister(nsnull);
    944898        rc = RegisterSelfComponents(registrar, components,
    945                                     NS_ARRAY_LENGTH (components));
     899                                    NS_ARRAY_LENGTH(components));
    946900        if (NS_FAILED(rc))
    947901        {
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