int main(int argc, char *argv[]) { char *argp, *value; int err, nextArg, status; err = 0; mprCreate(argc, argv, MPR_USER_EVENTS_THREAD); app = mprAllocObj(App, manageApp); mprAddRoot(app); mprAddTerminator(terminating); mprAddStandardSignals(); setAppDefaults(); for (nextArg = 1; nextArg < argc && !err; nextArg++) { argp = argv[nextArg]; if (*argp != '-') { break; } if (strcmp(argp, "--args") == 0) { /* Args to pass to service */ if (nextArg >= argc) { err++; } else { app->serviceArgs = argv[++nextArg]; } } else if (strcmp(argp, "--console") == 0) { /* Does nothing. Here for compatibility with windows watcher */ } else if (strcmp(argp, "--daemon") == 0) { app->runAsDaemon++; #if FUTURE } else if (strcmp(argp, "--heartBeat") == 0) { /* Set the frequency to check on the program. */ if (nextArg >= argc) { err++; } else { app->heartBeatPeriod = atoi(argv[++nextArg]); } #endif } else if (strcmp(argp, "--home") == 0) { /* Change to this directory before starting the service */ if (nextArg >= argc) { err++; } else { app->serviceHome = sclone(argv[++nextArg]); } } else if (strcmp(argp, "--log") == 0) { /* Pass the log directive through to the service */ if (nextArg >= argc) { err++; } else { app->logSpec = sclone(argv[++nextArg]); mprStartLogging(app->logSpec, 0); mprSetCmdlineLogging(1); } } else if (strcmp(argp, "--name") == 0) { if (nextArg >= argc) { err++; } else { app->serviceName = sclone(argv[++nextArg]); } } else if (strcmp(argp, "--pidfile") == 0) { if (nextArg >= argc) { err++; } else { app->pidPath = sclone(argv[++nextArg]); } } else if (strcmp(argp, "--program") == 0) { if (nextArg >= argc) { err++; } else { app->serviceProgram = sclone(argv[++nextArg]); } } else if (strcmp(argp, "--retries") == 0) { if (nextArg >= argc) { err++; } else { app->retries = atoi(argv[++nextArg]); } } else if (strcmp(argp, "--signal") == 0) { if (nextArg >= argc) { err++; } else { value = argv[++nextArg]; if (smatch(value, "SIGABRT")) { app->signal = SIGABRT; } else if (smatch(value, "SIGINT")) { app->signal = SIGINT; } else if (smatch(value, "SIGHUP")) { app->signal = SIGHUP; } else if (smatch(value, "SIGQUIT")) { app->signal = SIGQUIT; } else if (smatch(value, "SIGTERM")) { app->signal = SIGTERM; } else if (smatch(value, "SIGUSR1")) { app->signal = SIGUSR1; } else if (smatch(value, "SIGUSR2")) { app->signal = SIGUSR2; } else { app->signal = atoi(argv[++nextArg]); } } } else if (strcmp(argp, "--verbose") == 0 || strcmp(argp, "-v") == 0) { mprSetLogLevel(1); } else { err++; break; } } if (nextArg >= argc) { err++; } if (err) { mprUserError("Bad command line: \n" " Usage: %s [commands]\n" " Switches:\n" " --args # Args to pass to service\n" " --daemon # Run manager as a daemon\n" " --home path # Home directory for service\n" " --log logFile:level # Log directive for service\n" " --retries count # Max count of app restarts\n" " --name name # Name of the service to manage\n" " --pidfile path # Location of the pid file\n" " --program path # Service program to start\n" " --signal signo # Signal number to terminate service\n" " --verbose # Show command feedback\n" #if FUTURE " --heartBeat interval # Heart beat interval period (secs) \n" #endif " Commands:\n" " disable # Disable the service\n" " enable # Enable the service\n" " install # Install the service\n" " run # Run and watch over the service\n" " start # Start the service\n" " stop # Start the service\n" " uninstall # Uninstall the service\n" , app->appName); return -1; } if (!app->pidPath) { app->pidPath = sjoin(app->pidDir, "/", app->serviceName, ".pid", NULL); } if (app->runAsDaemon) { makeDaemon(); } status = 0; if (getuid() != 0) { mprUserError("Must run with administrator privilege. Use sudo."); status = 1; } else if (mprStart() < 0) { mprUserError("Can't start MPR for %s", mprGetAppName()); status = 2; } else { mprStartEventsThread(); for (; nextArg < argc; nextArg++) { if (!process(argv[nextArg], 0)) { status = 3; break; } } } mprDestroy(MPR_EXIT_DEFAULT); return status; }
//--------------------------------------------------------------------------- int ACE_MAIN(int argc, ACE_TCHAR *argv[]) { // 환경설정 (제일 먼저 초기화 해야함) procArguments(argc, argv); // 로그 if(initLog() < 0) { printf("로그 초기화를 실패했으므로 프로그램을 종료합니다.\n"); return -1; } //----------------------------------------------------------------------- // 데몬 만들기 //----------------------------------------------------------------------- // acceptor 가 초기화 된 후 데몬을 만들게 되면, 부모프로세스가 제거되면서 // listen 소켓도 같이 제거된다. 그러므로 acceptor 를 초기화 하기 전에 // 데몬을 먼저 만들어야 한다. if(Config::instance()->process.daemon == true) { if(makeDaemon() < 0) { printf("데몬으로 만들기를 실패했으므로 프로그램을 종료합니다.\n"); return -1; } } PAS_NOTICE1("%s", compile_date); // 시그널 핸들러 PasSignalHandler* pSignalHandler = new PasSignalHandler; initSignal(pSignalHandler); //------------------ // 각 모듈의 초기화 //------------------ HTTP::Request::HeaderBuffBytes = HTTP::Response::HeaderBuffBytes = Config::instance()->process.HttpHeaderBufferBytes; increseFdLimit(); // PAS 공식 로그 char hostName[32]; gethostname(hostName, sizeof(hostName)-1); PasDataLog::setPasAddr(hostName); // 메모리 매니저 초기화 //initMessageBlockManager(); if (readMBconfig() < 0) { printf("메모리 풀 컨피그 설정값을 확인하세요.\n"); PAS_ERROR("메모리 풀 컨피그 설정값을 확인하세요.\n"); return -1; } const int numWorkerThread = Config::instance()->thread.numWorker; // 리액터 ACE_Reactor* pReactor = ReactorPool::instance()->createMaster(); ReactorPool::instance()->createWorkers(numWorkerThread); ACE_Reactor* pGlobalReactor = ACE_Reactor::instance(); PAS_NOTICE3("REACTOR: Master=%X, Global=%X, Master=%x", pReactor, pGlobalReactor, ReactorPool::instance()->masterReactor()); // Listen 포트 설정 PAS_NOTICE("Listen Socket Activate"); PasAcceptor* pAcceptor = new PasAcceptor(pReactor); const int listenPort = Config::instance()->network.listenPort; // mIDC 내의 서버를 감시하는 쪽에 mwatch 전달하기 위해 메시지 작성한다. Util2::setMwatchMsg(listenPort); // acceptor 기동 if(pAcceptor->open(listenPort) < 0) { PAS_ERROR1("Listen 소켓 생성 실패, Port[%d]\n", listenPort); PAS_ERROR("프로그램 종료\n"); printf("Listen 소켓 생성 실패, Port[%d]\n", listenPort); printf("프로그램 종료\n"); return -1; } // 쓰레드 매니저 ACE_Thread_Manager* pTManager = ACE_Thread_Manager::instance(); // monitor 보고리를 위한 thread 를 생성한다. MonitorReporter *monitor = MonitorReporter::instance(pTManager); monitor->activate(THR_NEW_LWP | THR_JOINABLE); WatchReporter *watch = WatchReporter::instance(pTManager); watch->activate(THR_NEW_LWP | THR_JOINABLE); // UserInfo 관리를 위한 thread 를 생성한다. UserInfoMng *userInfoMng = UserInfoMng::instance(pTManager); userInfoMng->activate(THR_NEW_LWP | THR_JOINABLE); // phone trace 를 위한 thread 를 생성한다. PhoneTraceMng *phoneTraceMng = PhoneTraceMng::instance(pTManager); phoneTraceMng->setDataFile((char*)"trace.acl"); phoneTraceMng->activate(THR_NEW_LWP | THR_JOINABLE); // 공지 처리 (Stat Filter) 를 위한 thread 를 생성한다. StatFilterMng *statFilterMng = StatFilterMng::instance(pTManager); statFilterMng->setDataFile((char*)"k_stat.cfg"); statFilterMng->activate(THR_NEW_LWP | THR_JOINABLE); // ACL 초기화 if(Config::instance()->acl.enable) initACL(); CGI::cgiSetupConstants(); // Create AuthAgent Thread AuthAgent *authAgent = AuthAgent::instance(pTManager); authAgent->activate(THR_NEW_LWP | THR_JOINABLE); //usleep(1000); // 내부 정보 (sysinfo) 출력를 위한 Thread SysInfo *sysInfo = SysInfo::instance(pTManager); sysInfo->activate(THR_NEW_LWP | THR_JOINABLE); // hash key 로그 작성을 위한 초기화. HashKey::prepare(); // 로그 화일을 먼저 만들어 놓는다. 테스트시에 편하다. (tail -f ) PasDataLog::instance(); // accept event 핸들러 등록 pReactor->register_handler(pAcceptor, ACE_Event_Handler::ACCEPT_MASK); // 이벤트 디멀티플렉싱 PAS_NOTICE("Master Reactor Start"); pReactor->run_event_loop(); PAS_NOTICE("Master Reactor Stop"); ReactorPool::instance()->stopWorkers(); /*--- Reactor 가 종료된 경우 아래 라인으로 진행된다. ---*/ stopACL(); // ACL 종료 userInfoMng->stop(); monitor->stop(); watch->stop(); phoneTraceMng->putq(new ACE_Message_Block()); statFilterMng->putq(new ACE_Message_Block()); sysInfo->putq(new ACE_Message_Block()); authAgent->putq(new ACE_Message_Block()); DNS::Manager::instance()->removeAllQuerier(); // 모든 쓰레드 종료 대기 PAS_NOTICE("Waiting for all threads to stop"); pTManager->wait(); delete phoneTraceMng; delete statFilterMng; delete sysInfo; // 생성한 동적 객체 삭제 delete pSignalHandler; PAS_NOTICE("======= PAS GW Stop ======="); return 0; }