Changeset 36466 in vbox
- Timestamp:
- Mar 29, 2011 5:40:35 PM (14 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/Makefile.kmk
r35967 r36466 245 245 246 246 VBoxSVC_CXXFLAGS = $(filter-out -Wno-unused,$(TEMPLATE_VBOXMAINEXE_CXXFLAGS)) 247 ## @todo We're disabling optimizations on FreeBSD to work around strange linker248 # errors in release builds. Figure out why and how to work around it in a249 # more optimal fashion.250 VBoxSVC_CXXFLAGS.freebsd = -O0251 247 252 248 VBoxSVC_INCS = \ -
trunk/src/VBox/Main/src-server/xpcom/server.cpp
r35976 r36466 615 615 //////////////////////////////////////////////////////////////////////////////// 616 616 617 typedef NSFactoryDestructorProcPtr NSFactoryCons ructorProcPtr;617 typedef NSFactoryDestructorProcPtr NSFactoryConstructorProcPtr; 618 618 619 619 /** … … 621 621 * 622 622 * nsModuleComponentInfo lacks the factory construction callback, here we add 623 * it. This callback is called by NS_NewGenericFactoryEx() after a624 * nsGenericFactory instance is successfully created.623 * it. This callback is called straight after a nsGenericFactory instance is 624 * successfully created in RegisterSelfComponents. 625 625 */ 626 struct nsModuleComponentInfo Ex : nsModuleComponentInfo626 struct nsModuleComponentInfoPlusFactoryConstructor 627 627 { 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; 659 630 /** (optional) Factory Construction Callback */ 660 NSFactoryCons ructorProcPtr mFactoryConstructor;631 NSFactoryConstructorProcPtr mFactoryConstructor; 661 632 }; 662 633 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 */ 640 static nsresult 641 RegisterSelfComponents(nsIComponentRegistrar *registrar, 642 const nsModuleComponentInfoPlusFactoryConstructor *aComponents, 643 PRUint32 count) 666 644 { 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 675 static ipcIService *gIpcServ = nsnull; 676 static const char *g_pszPidFile = NULL; 677 678 class 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 693 static 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 715 static 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 764 end: 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 774 int 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 = { 668 860 "VirtualBox component", 669 861 CLSID_VirtualBox, … … 676 868 NULL, // language helper 677 869 &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 855 871 }; 856 872 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 }; 925 879 926 880 do … … 943 897 registrar->AutoRegister(nsnull); 944 898 rc = RegisterSelfComponents(registrar, components, 945 NS_ARRAY_LENGTH 899 NS_ARRAY_LENGTH(components)); 946 900 if (NS_FAILED(rc)) 947 901 {
Note:
See TracChangeset
for help on using the changeset viewer.