int Mpr::platformStart(int startFlags) { if (startFlags & MPR_KILLABLE) { writePid(); } return 0; }
// Shamelessly lifted from pg_autovacuum... static void daemonize(void) { pid_t pid; pid = fork(); if (pid == (pid_t) - 1) { LogMessage(_("Cannot disassociate from controlling TTY"), LOG_ERROR); exit(1); } else if (pid) { writePid(pid); exit(0); } #ifdef HAVE_SETSID if (setsid() < 0) { LogMessage(_("Cannot disassociate from controlling TTY"), LOG_ERROR); exit(1); } #endif }
void acquirePathLock() { string name = ( boost::filesystem::path( dbpath ) / "mongod.lock" ).string(); #ifdef _WIN32 lockFileHandle = CreateFileA( name.c_str(), GENERIC_READ | GENERIC_WRITE, 0 /* do not allow anyone else access */, NULL, OPEN_ALWAYS /* success if fh can open */, 0, NULL ); if (lockFileHandle == INVALID_HANDLE_VALUE) { DWORD code = GetLastError(); char *msg; FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL); string m = msg; str::stripTrailing(m, "\r\n"); uasserted( 13627 , str::stream() << "Unable to create/open lock file: " << name << ' ' << m << ". Is a mongod instance already running?" ); } lockFile = _open_osfhandle((intptr_t)lockFileHandle, 0); #else lockFile = open( name.c_str(), O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO ); if( lockFile <= 0 ) { uasserted( 10309 , str::stream() << "Unable to create/open lock file: " << name << ' ' << errnoWithDescription() << " Is a mongod instance already running?" ); } if (flock( lockFile, LOCK_EX | LOCK_NB ) != 0) { close ( lockFile ); lockFile = 0; uassert( 10310 , "Unable to lock file: " + name + ". Is a mongod instance already running?", 0 ); } #endif #ifdef _WIN32 uassert( 13625, "Unable to truncate lock file", _chsize(lockFile, 0) == 0); writePid( lockFile ); _commit( lockFile ); #else uassert( 13342, "Unable to truncate lock file", ftruncate(lockFile, 0) == 0); writePid( lockFile ); fsync( lockFile ); flushMyDirectory(name); #endif }
int main(int argc, const char * argv[]) { // insert code here... printf("start push server...\n"); signal(SIGPIPE, SIG_IGN); CPushApp::GetInstance()->Init(); CPushApp::GetInstance()->Start(); writePid(); while (true) { S_Sleep(1000); } return 0; }
int PidFile::testAndRelockPidFile( const char * pPidFile, int pid ) { struct stat st; if (( nio_stat( pPidFile, &st ) == -1 )|| ( st.st_mtime != m_stPid.st_mtime )|| ( st.st_size != m_stPid.st_size )|| ( st.st_ino != m_stPid.st_ino )) { closePidFile(); int ret = lockPidFile( pPidFile ); if ( !ret ) ret = writePid( pid ); return ret; } return 0; }
int main(int argc, char* argv[]) { if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { printf("Server Version: RouteServer/%s\n", VERSION); printf("Server Build: %s %s\n", __DATE__, __TIME__); return 0; } signal(SIGPIPE, SIG_IGN); srand(time(NULL)); CConfigFileReader config_file("routeserver.conf"); char* listen_ip = config_file.GetConfigName("ListenIP"); char* str_listen_msg_port = config_file.GetConfigName("ListenMsgPort"); if (!listen_ip || !str_listen_msg_port) { log("config item missing, exit... "); return -1; } uint16_t listen_msg_port = atoi(str_listen_msg_port); int ret = netlib_init(); if (ret == NETLIB_ERROR) return ret; CStrExplode listen_ip_list(listen_ip, ';'); for (uint32_t i = 0; i < listen_ip_list.GetItemCnt(); i++) { ret = netlib_listen(listen_ip_list.GetItem(i), listen_msg_port, route_serv_callback, NULL); if (ret == NETLIB_ERROR) return ret; } printf("server start listen on: %s:%d\n", listen_ip, listen_msg_port); init_routeconn_timer_callback(); printf("now enter the event loop...\n"); writePid(); netlib_eventloop(); return 0; }
int main(int argc, char *argv[]){ if(argc < 2) { printf("Wymagany jeden argument (plik do zapisu pid-u; plik nie musi sitniec)\n\n\n"); return 1; } else { srand(time(NULL)); pid_t pid; pid = fork(); intmax_t a = rand() * getpid(); int b = getpid()%10; printf("Moj pid:%d\n", (intmax_t) getpid()); printf("Moja zmienna[a:%d b: %d]\n", a, b); if(!pid) { printf("\nJestem potomkiem :D\n\n"); printf("\nNazwa systemu to \n"); execl("/bin/uname", "uname -a", NULL); } else printf("\nNie jestem potomkiem xD\n\n"); wait(NULL); printf("\nPaPa\n"); int localDescr = open(argv[1], O_RDWR | O_CREAT | O_APPEND); for (int i = 0; i < 10; i++) { if(pid) pid = fork(); } if(!writePid(getpid(), localDescr)) printf("Blad zapisu\n"); return 0; } }
int main(int argc, char **argv) { FdEventHandlerPtr listener; int i; int rc; int expire = 0, printConfig = 0; initAtoms(); CONFIG_VARIABLE(daemonise, CONFIG_BOOLEAN, "Run as a daemon"); CONFIG_VARIABLE(pidFile, CONFIG_ATOM, "File with pid of running daemon."); preinitChunks(); preinitLog(); preinitObject(); preinitIo(); preinitDns(); preinitServer(); preinitHttp(); preinitDiskcache(); preinitLocal(); preinitForbidden(); preinitSocks(); preinitOffline(); i = 1; while(i < argc) { if(argv[i][0] != '-') break; if(strcmp(argv[i], "--") == 0) { i++; break; } else if(strcmp(argv[i], "-h") == 0) { usage(argv[0]); exit(0); } else if(strcmp(argv[i], "-v") == 0) { printConfig = 1; i++; } else if(strcmp(argv[i], "-x") == 0) { expire = 1; i++; } else if(strcmp(argv[i], "-c") == 0) { i++; if(i >= argc) { usage(argv[0]); exit(1); } if(configFile) releaseAtom(configFile); configFile = internAtom(argv[i]); i++; } else { usage(argv[0]); exit(1); } } if(configFile) configFile = expandTilde(configFile); if(configFile == NULL) { configFile = expandTilde(internAtom("~/.polipo")); if(configFile) if(access(configFile->string, F_OK) < 0) { releaseAtom(configFile); configFile = NULL; } } if(configFile == NULL) { if(access("/etc/polipo/config", F_OK) >= 0) configFile = internAtom("/etc/polipo/config"); if(configFile && access(configFile->string, F_OK) < 0) { releaseAtom(configFile); configFile = NULL; } } rc = parseConfigFile(configFile); if(rc < 0) exit(1); while(i < argc) { rc = parseConfigLine(argv[i], "command line", 0, 0); if(rc < 0) exit(1); i++; } initChunks(); initLog(); initObject(); if(!expire && !printConfig) initEvents(); initIo(); initDns(); initHttp(); initServer(); initDiskcache(); initForbidden(); initSocks(); initOffline(); if(printConfig) { printConfigVariables(stdout, 0); exit(0); } if(expire) { expireDiskObjects(); exit(0); } if(daemonise) do_daemonise(logFile == NULL || logFile->length == 0); if(pidFile) writePid(pidFile->string); listener = create_listener(proxyAddress->string, proxyPort, httpAccept, NULL); if(!listener) { if(pidFile) unlink(pidFile->string); exit(1); } eventLoop(); if(pidFile) unlink(pidFile->string); return 0; }
void acquirePathLock(bool doingRepair) { string name = ( boost::filesystem::path( dbpath ) / "mongod.lock" ).string(); bool oldFile = false; if ( boost::filesystem::exists( name ) && boost::filesystem::file_size( name ) > 0 ) { oldFile = true; } #ifdef _WIN32 lockFileHandle = CreateFileA( name.c_str(), GENERIC_READ | GENERIC_WRITE, 0 /* do not allow anyone else access */, NULL, OPEN_ALWAYS /* success if fh can open */, 0, NULL ); if (lockFileHandle == INVALID_HANDLE_VALUE) { DWORD code = GetLastError(); char *msg; FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL); string m = msg; str::stripTrailing(m, "\r\n"); uasserted( 13627 , str::stream() << "Unable to create/open lock file: " << name << ' ' << m << ". Is a mongod instance already running?" ); } lockFile = _open_osfhandle((intptr_t)lockFileHandle, 0); #else lockFile = open( name.c_str(), O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO ); if( lockFile <= 0 ) { uasserted( 10309 , str::stream() << "Unable to create/open lock file: " << name << ' ' << errnoWithDescription() << " Is a mongod instance already running?" ); } if (flock( lockFile, LOCK_EX | LOCK_NB ) != 0) { close ( lockFile ); lockFile = 0; uassert( 10310 , "Unable to lock file: " + name + ". Is a mongod instance already running?", 0 ); } #endif if ( oldFile ) { // we check this here because we want to see if we can get the lock // if we can't, then its probably just another mongod running string errmsg; if (doingRepair && dur::haveJournalFiles()) { errmsg = "************** \n" "You specified --repair but there are dirty journal files. Please\n" "restart without --repair to allow the journal files to be replayed.\n" "If you wish to repair all databases, please shutdown cleanly and\n" "run with --repair again.\n" "**************"; } else if (cmdLine.dur) { if (!dur::haveJournalFiles(/*anyFiles=*/true)) { // Passing anyFiles=true as we are trying to protect against starting in an // unclean state with the journal directory unmounted. If there are any files, // even prealloc files, then it means that it is mounted so we can continue. // Previously there was an issue (SERVER-5056) where we would fail to start up // if killed during prealloc. vector<string> dbnames; getDatabaseNames( dbnames ); if ( dbnames.size() == 0 ) { // this means that mongod crashed // between initial startup and when journaling was initialized // it is safe to continue } else { errmsg = str::stream() << "************** \n" << "old lock file: " << name << ". probably means unclean shutdown,\n" << "but there are no journal files to recover.\n" << "this is likely human error or filesystem corruption.\n" << "please make sure that your journal directory is mounted.\n" << "found " << dbnames.size() << " dbs.\n" << "see: http://dochub.mongodb.org/core/repair for more information\n" << "*************"; } } } else { if (!dur::haveJournalFiles() && !doingRepair) { errmsg = str::stream() << "************** \n" << "Unclean shutdown detected.\n" << "Please visit http://dochub.mongodb.org/core/repair for recovery instructions.\n" << "*************"; } } if (!errmsg.empty()) { cout << errmsg << endl; #ifdef _WIN32 CloseHandle( lockFileHandle ); #else close ( lockFile ); #endif lockFile = 0; uassert( 12596 , "old lock file" , 0 ); } } // Not related to lock file, but this is where we handle unclean shutdown if( !cmdLine.dur && dur::haveJournalFiles() ) { cout << "**************" << endl; cout << "Error: journal files are present in journal directory, yet starting without journaling enabled." << endl; cout << "It is recommended that you start with journaling enabled so that recovery may occur." << endl; cout << "**************" << endl; uasserted(13597, "can't start without --journal enabled when journal/ files are present"); } #ifdef _WIN32 uassert( 13625, "Unable to truncate lock file", _chsize(lockFile, 0) == 0); writePid( lockFile ); _commit( lockFile ); #else uassert( 13342, "Unable to truncate lock file", ftruncate(lockFile, 0) == 0); writePid( lockFile ); fsync( lockFile ); flushMyDirectory(name); #endif }
static void runService() { MprTime mark; char **av, *env[3], **argv; int err, i, status, ac, next; app->servicePid = 0; atexit(cleanup); mprLog(1, "%s: Watching over %s", app->appName, app->serviceProgram); if (access(app->serviceProgram, X_OK) < 0) { mprError("start: can't access %s, errno %d", app->serviceProgram, mprGetOsError()); return; } if (writePid(getpid()) < 0) { return; } mark = mprGetTime(); while (!mprIsStopping()) { if (mprGetElapsedTime(mark) > (3600 * 1000)) { mark = mprGetTime(); app->restartCount = 0; app->restartWarned = 0; } if (app->servicePid == 0) { if (app->restartCount >= app->retries) { if (! app->restartWarned) { mprError("Too many restarts for %s, %d in ths last hour", app->serviceProgram, app->restartCount); mprError("Suspending restarts for one hour"); app->restartWarned++; } mprSleep(60 * 1000); continue; } /* Create the child */ app->servicePid = vfork(); if (app->servicePid < 0) { mprError("Can't fork new process to run %s", app->serviceProgram); continue; } else if (app->servicePid == 0) { /* Child */ umask(022); setsid(); mprLog(1, "%s: Change dir to %s", app->appName, app->serviceHome); if (chdir(app->serviceHome) < 0) {} for (i = 3; i < 128; i++) { close(i); } if (app->serviceArgs && *app->serviceArgs) { ac = mprMakeArgv(app->serviceArgs, &av, 0); } else { ac = 0; } argv = mprAlloc(sizeof(char*) * (6 + ac)); env[0] = sjoin("LD_LIBRARY_PATH=", app->serviceHome, NULL); env[1] = sjoin("PATH=", getenv("PATH"), NULL); env[2] = 0; next = 0; argv[next++] = app->serviceProgram; if (app->logSpec) { argv[next++] = "--log"; argv[next++] = (char*) app->logSpec; } for (i = 0; i < ac; i++) { argv[next++] = av[i]; } argv[next++] = 0; mprLog(1, "%s: Running %s", app->appName, app->serviceProgram); for (i = 1; argv[i]; i++) { mprLog(1, "%s: argv[%d] = %s", app->appName, i, argv[i]); } execve(app->serviceProgram, argv, (char**) &env); /* Should not get here */ err = errno; mprError("%s: Can't exec %s, err %d, cwd %s", app->appName, app->serviceProgram, err, app->serviceHome); exit(MPR_ERR_CANT_INITIALIZE); } /* Parent */ mprLog(1, "%s: create child %s at pid %d", app->appName, app->serviceProgram, app->servicePid); app->restartCount++; waitpid(app->servicePid, &status, 0); mprLog(1, "%s: %s has exited with status %d", app->appName, app->serviceProgram, WEXITSTATUS(status)); if (!mprIsStopping()) { mprLog(1, "%s: Restarting %s (%d/%d)...", app->appName, app->serviceProgram, app->restartCount, app->retries); } app->servicePid = 0; } } }
Server::Server() : m_lockFileName(Config::Instance()->lockFileName), m_pidFileName(Config::Instance()->pidFileName) { pid_t pid, sid, parent; int lfp = -1; struct stat sb; /* already a daemon */ if(getppid() == 1) return; if(m_lockFileName.size()) { if (stat(m_lockFileName.c_str(), &sb) != -1) { syslog(LOG_INFO, "another process running?"); if( getProcIdByName(__progname) > 0) { syslog(LOG_ERR, "exit"); exit(EXIT_FAILURE); } else { ::remove(m_lockFileName.c_str()); } } lfp = open(m_lockFileName.c_str(),O_RDWR|O_CREAT,0640); if(lfp < 0) { syslog(LOG_ERR, "unable to create lock file %s, code=%d (%s). exit", m_lockFileName.c_str(), errno, strerror(errno)); exit(EXIT_FAILURE); } } if(getuid() == 0 || geteuid() == 0) { struct passwd *pw = getpwnam(Config::Instance()->asUser.c_str()); if(pw) { syslog(LOG_NOTICE, "setting user to %s",Config::Instance()->asUser.c_str()); if(setuid(pw->pw_uid)) syslog(LOG_ERR,"error set uid"); } } signal(SIGCHLD,child_handler); signal(SIGUSR1,child_handler); signal(SIGALRM,child_handler); pid = fork(); if(pid < 0) { syslog(LOG_ERR, "unable to fork daemon, code=%d (%s). exit", errno, strerror(errno)); exit(EXIT_FAILURE); } if(pid > 0) { alarm(2); pause(); exit(EXIT_FAILURE); } parent = getppid(); signal(SIGCHLD,SIG_DFL); signal(SIGTSTP,SIG_IGN); signal(SIGTTOU,SIG_IGN); signal(SIGTTIN,SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGTERM,SIG_DFL); signal(SIGPIPE,SIG_IGN); signal(SIGRTMIN,SIG_DFL); umask(007); sid = setsid(); if(sid < 0) { syslog(LOG_ERR, "unable to create a new session, code %d (%s)", errno, strerror(errno)); // exit(EXIT_FAILURE); } if((chdir("/")) < 0) { syslog(LOG_ERR, "unable to change directory to %s, code %d (%s). exit", "/", errno, strerror(errno)); // exit(EXIT_FAILURE); } if(!freopen("/dev/null", "r", stdin)) syslog(LOG_ERR, "unable to change stdin"); if(Config::Instance()->debug) { if(freopen(Config::Instance()->debug_file.c_str(), "w", stdout)) syslog(LOG_ERR, "unable to change stdout to:%s",Config::Instance()->debug_file.c_str()); if(!freopen(Config::Instance()->debug_file.c_str(), "w", stderr)) syslog(LOG_ERR, "unable to change stdin %s",Config::Instance()->debug_file.c_str()); printf("start\n"); } else { if(freopen("/dev/null", "w", stdout)) syslog(LOG_ERR, "unable to change stdout"); if(!freopen("/dev/null", "w", stderr)) syslog(LOG_ERR, "unable to change stderr"); kill(parent, SIGUSR1); } struct sched_param param; param.sched_priority = 49; if(sched_setscheduler(0, SCHED_FIFO, ¶m) == -1) { syslog(LOG_ERR,"sched_setscheduler failed"); //exit(-1); } if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1) { syslog(LOG_ERR,"mlockall failed"); //exit(-2); } writePid(m_pidFileName); syslog(LOG_NOTICE, "staring: done"); }
int main(int argc, char* argv[]) { if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { printf("Server Version: HttpMsgServer/%s\n", VERSION); printf("Server Build: %s %s\n", __DATE__, __TIME__); return 0; } signal(SIGPIPE, SIG_IGN); srand(time(NULL)); log("MsgServer max files can open: %d ", getdtablesize()); CConfigFileReader config_file("httpmsgserver.conf"); char* listen_ip = config_file.GetConfigName("ListenIP"); char* str_listen_port = config_file.GetConfigName("ListenPort"); uint32_t db_server_count = 0; serv_info_t* db_server_list = read_server_config(&config_file, "DBServerIP", "DBServerPort", db_server_count); uint32_t route_server_count = 0; serv_info_t* route_server_list = read_server_config(&config_file, "RouteServerIP", "RouteServerPort", route_server_count); // 到BusinessServer的开多个并发的连接 uint32_t concurrent_db_conn_cnt = DEFAULT_CONCURRENT_DB_CONN_CNT; uint32_t db_server_count2 = db_server_count * DEFAULT_CONCURRENT_DB_CONN_CNT; char* concurrent_db_conn = config_file.GetConfigName("ConcurrentDBConnCnt"); if (concurrent_db_conn) { concurrent_db_conn_cnt = atoi(concurrent_db_conn); db_server_count2 = db_server_count * concurrent_db_conn_cnt; } serv_info_t* db_server_list2 = NULL; if (db_server_count2 > 0) { db_server_list2 = new serv_info_t [ db_server_count2]; for (uint32_t i = 0; i < db_server_count2; i++) { db_server_list2[i].server_ip = db_server_list[i / concurrent_db_conn_cnt].server_ip.c_str(); db_server_list2[i].server_port = db_server_list[i / concurrent_db_conn_cnt].server_port; } } if (!listen_ip || !str_listen_port) { log("config file miss, exit... "); return -1; } uint16_t listen_port = atoi(str_listen_port); int ret = netlib_init(); if (ret == NETLIB_ERROR) return ret; CStrExplode listen_ip_list(listen_ip, ';'); for (uint32_t i = 0; i < listen_ip_list.GetItemCnt(); i++) { ret = netlib_listen(listen_ip_list.GetItem(i), listen_port, http_callback, NULL); if (ret == NETLIB_ERROR) return ret; } printf("server start listen on: %s:%d\n", listen_ip, listen_port); init_http_conn(); if (db_server_count > 0) { HTTP::init_db_serv_conn(db_server_list2, db_server_count2, concurrent_db_conn_cnt); } if (route_server_count > 0) { HTTP::init_route_serv_conn(route_server_list, route_server_count); } printf("now enter the event loop...\n"); writePid(); netlib_eventloop(); return 0; }
void CPCD::Process::do_exec() { unsigned i; #ifdef _WIN32 Vector<BaseString> saved; char *cwd = 0; save_environment(m_env.c_str(), saved); #endif setup_environment(m_env.c_str()); char **argv = BaseString::argify(m_path.c_str(), m_args.c_str()); if(strlen(m_cwd.c_str()) > 0) { #ifdef _WIN32 cwd = getcwd(0, 0); if(!cwd) { logger.critical("Couldn't getcwd before spawn"); } #endif int err = chdir(m_cwd.c_str()); if(err == -1) { BaseString err; logger.error("%s: %s\n", m_cwd.c_str(), strerror(errno)); _exit(1); } } #ifndef _WIN32 Vector<BaseString> ulimit; m_ulimit.split(ulimit); for(i = 0; i<ulimit.size(); i++){ if(ulimit[i].trim().length() > 0 && set_ulimit(ulimit[i]) != 0){ _exit(1); } } #endif const char *nul = IF_WIN("nul:", "/dev/null"); int fdnull = open(nul, O_RDWR, 0); if(fdnull == -1) { logger.error("Cannot open `%s': %s\n", nul, strerror(errno)); _exit(1); } BaseString * redirects[] = { &m_stdin, &m_stdout, &m_stderr }; int fds[3]; #ifdef _WIN32 int std_dups[3]; #endif for (i = 0; i < 3; i++) { #ifdef _WIN32 std_dups[i] = dup(i); #endif if (redirects[i]->empty()) { #ifndef DEBUG dup2(fdnull, i); #endif continue; } if((* redirects[i]) == "2>&1" && i == 2){ dup2(fds[1], 2); continue; } /** * Make file */ int flags = 0; int mode = S_IRUSR | S_IWUSR ; if(i == 0){ flags |= O_RDONLY; } else { flags |= O_WRONLY | O_CREAT | O_APPEND; } int f = fds[i]= open(redirects[i]->c_str(), flags, mode); if(f == -1){ logger.error("Cannot redirect %u to/from '%s' : %s\n", i, redirects[i]->c_str(), strerror(errno)); _exit(1); } dup2(f, i); #ifdef _WIN32 close(f); #endif } #ifndef _WIN32 /* Close all filedescriptors */ for(i = STDERR_FILENO+1; (int)i < getdtablesize(); i++) close(i); execv(m_path.c_str(), argv); /* XXX If we reach this point, an error has occurred, but it's kind of hard * to report it, because we've closed all files... So we should probably * create a new logger here */ logger.error("Exec failed: %s\n", strerror(errno)); /* NOTREACHED */ #else // Get full path to cygwins shell FILE *fpipe = _popen("sh -c 'cygpath -w `which sh`'", "rt"); char buf[MAX_PATH]; require(fgets(buf, MAX_PATH - 1, fpipe)); fclose(fpipe); BaseString sh; sh.assign(buf); sh.trim("\n"); sh.append(".exe"); BaseString shcmd; shcmd.assfmt("%s -c '%s %s'", sh.c_str(), m_path.c_str(), m_args.c_str()); PROCESS_INFORMATION pi = {0}; STARTUPINFO si = {sizeof(STARTUPINFO), 0}; si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = (HANDLE)_get_osfhandle(0); si.hStdOutput = (HANDLE)_get_osfhandle(1); si.hStdError = (HANDLE)_get_osfhandle(2); if(!CreateProcessA(sh.c_str(), (LPSTR)shcmd.c_str(), NULL, NULL, TRUE, CREATE_SUSPENDED, // Resumed after assigned to Job NULL, NULL, &si, &pi)) { char* message; DWORD err = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&message, 0, NULL ); logger.error("CreateProcess failed, error: %d, message: '%s'", err, message); LocalFree(message); } HANDLE proc = pi.hProcess; require(proc); // Job control require(m_job = CreateJobObject(0, 0)); require(AssignProcessToJobObject(m_job, proc)); // Resum process after it has been added to Job ResumeThread(pi.hThread); CloseHandle(pi.hThread); // go back up to original cwd if(chdir(cwd)) { logger.critical("Couldn't go back to saved cwd after spawn()"); logger.critical("errno: %d, strerror: %s", errno, strerror(errno)); } free(cwd); // get back to original std i/o for(i = 0; i < 3; i++) { dup2(std_dups[i], i); close(std_dups[i]); } for (i = 0; i < saved.size(); i++) { putenv(saved[i].c_str()); } logger.debug("'%s' has been started", shcmd.c_str()); DWORD exitcode; BOOL result = GetExitCodeProcess(proc, &exitcode); //maybe a short running process if (result && exitcode != 259) { m_status = STOPPED; logger.warning("Process terminated early"); } int pid = GetProcessId(proc); if (!pid) logger.critical("GetProcessId failed, error: %d!", GetLastError()); logger.debug("new pid %d", pid); CloseHandle(proc); m_status = RUNNING; writePid(pid); #endif close(fdnull); }
int main(int argc, char* argv[]) { if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { printf("Server Version: DBProxyServer/%s\n", VERSION); printf("Server Build: %s %s\n", __DATE__, __TIME__); return 0; } signal(SIGPIPE, SIG_IGN); srand(time(NULL)); CacheManager* pCacheManager = CacheManager::getInstance(CONFIGFILE_NAME); if (!pCacheManager) { log("CacheManager init failed"); return -1; } CDBManager* pDBManager = CDBManager::getInstance(CONFIGFILE_NAME); if (!pDBManager) { log("DBManager init failed"); return -1; } // 主线程初始化单例,不然在工作线程可能会出现多次初始化 if (!CAudioModel::getInstance()) { return -1; } if (!CGroupMessageModel::getInstance()) { return -1; } if (!CGroupModel::getInstance()) { return -1; } if (!CMessageModel::getInstance()) { return -1; } if (!CSessionModel::getInstance()) { return -1; } if(!CRelationModel::getInstance()) { return -1; } if (!CUserModel::getInstance()) { return -1; } if (!CFileModel::getInstance()) { return -1; } CConfigFileReader config_file(CONFIGFILE_NAME); char* listen_ip = config_file.GetConfigName("ListenIP"); char* str_listen_port = config_file.GetConfigName("ListenPort"); char* str_thread_num = config_file.GetConfigName("ThreadNum"); char* str_file_site = config_file.GetConfigName("MsfsSite"); char* str_aes_key = config_file.GetConfigName("aesKey"); if (!listen_ip || !str_listen_port || !str_thread_num || !str_file_site || !str_aes_key) { log("missing ListenIP/ListenPort/ThreadNum/MsfsSite/aesKey, exit..."); return -1; } if(strlen(str_aes_key) != 32) { log("aes key is invalied"); return -2; } string strAesKey(str_aes_key, 32); CAes cAes = CAes(strAesKey); string strAudio = "[语音]"; char* pAudioEnc; uint32_t nOutLen; if(cAes.Encrypt(strAudio.c_str(), strAudio.length(), &pAudioEnc, nOutLen) == 0) { strAudioEnc.clear(); strAudioEnc.append(pAudioEnc, nOutLen); cAes.Free(pAudioEnc); } uint16_t listen_port = atoi(str_listen_port); uint32_t thread_num = atoi(str_thread_num); string strFileSite(str_file_site); CAudioModel::getInstance()->setUrl(strFileSite); int ret = netlib_init(); if (ret == NETLIB_ERROR) return ret; /// yunfan add 2014.9.28 // for 603 push curl_global_init(CURL_GLOBAL_ALL); //初始化libcurl,CURL_GLOBAL_ALL初始化所有可能的调用 /// yunfan add end init_proxy_conn(thread_num); CSyncCenter::getInstance()->init(); CSyncCenter::getInstance()->startSync(); CStrExplode listen_ip_list(listen_ip, ';'); for (uint32_t i = 0; i < listen_ip_list.GetItemCnt(); i++) { ret = netlib_listen(listen_ip_list.GetItem(i), listen_port, proxy_serv_callback, NULL); if (ret == NETLIB_ERROR) return ret; } printf("server start listen on: %s:%d\n", listen_ip, listen_port); printf("now enter the event loop...\n"); writePid(); netlib_eventloop(10); return 0; }
/** * Program pooling a directory, and doing a scheduling. **/ int main (int argc, char** argv) { initPins(); adc_init(); lcd_init(); /** The status does not exist at the launch of the schduler prgram*/ clearFile(); int pid=readPid(); stopIfPidExists(pid); writePid(); SetChrMode(); int nbSecond; int remainingSeconds; uchar intensity; uchar tmpintensity; int i; int valueInFile; time_t whenItsComplete ; char timestr[7]; pinMode (RELAY_IN, OUTPUT); // Permanent loop checking file. int cycle=0; while(1){ valueInFile=getCoundownValue(); #ifndef PROD printf("pause:%d,valueInFile:%d\n",pauseSt,valueInFile); #endif if(valueInFile>=0){ nbSecond=valueInFile; // The countdown whenItsComplete = time(NULL)+nbSecond; remainingSeconds=whenItsComplete-time(NULL); } else{remainingSeconds=-1;} #ifndef PROD printf("nbsecond:%d\n",nbSecond); #endif do { /** * Do a regular reset of the LCD **/ if(cycle%500==0){ lcd_init(); } else if(cycle%60==0){ resetLcd(); } /** * Write the remaining seconds **/ if(cycle%60==0){ writeRemaining(remainingSeconds); } /** * Increment only if not in pause (Cycle increments will be at the end of the cycle loop. **/ updateStandbyStatus(); cycle++; if(remainingSeconds>-1){ if(pauseSt==IS_RUNNING){ remainingSeconds=whenItsComplete-time(NULL); }else{ whenItsComplete=remainingSeconds+time(NULL); } openRelay(); if(lastImmobileState==0||(time(NULL)-lastImmobileState)<NBSECONDBEFORECREENSHUTDOWN){ digitalWrite (TRANSISTOR, LOW); } else{ digitalWrite (TRANSISTOR, HIGH); } int seconds=remainingSeconds%60; int hours=remainingSeconds/3600; int minutes=remainingSeconds/60%60; sprintf(timestr,"%02d:%02d:%02d",hours,minutes,seconds); goHome(); lcd_text(timestr); #ifndef PROD printf("%s\n",timestr); #endif sleep(1); } /** * Block measuring intensity */ if(cycle%20==0){ intensity=get_ADC_Result(); #ifndef PROD printf("Intensite: %d\n",intensity); #endif } #ifndef PROD printf("Remaining seconds %d,cycle=%d\n",remainingSeconds,cycle); #endif } while ( remainingSeconds>0&& !isFilePresent()); #ifndef PROD // printf("Sortie boucle décompte\n"); #endif /** * Every 10 ccyle there is a full reset of the screen. Otherwise it is light reset. **/ if(cycle%100==0){ lcd_init(); } nbSecond=0; /** * **/ if(valueInFile==NO_FILE){ goHome(); closeRelay(); digitalWrite (TRANSISTOR, HIGH); lcd_text("Expire " ); #ifndef PROD printf("Expire\n"); #endif } else if(valueInFile==TV_ON){ goHome(); openRelay(); digitalWrite (TRANSISTOR, LOW); lcd_text("Tele on " ); } else if(valueInFile==TV_OFF){ goHome(); digitalWrite (TRANSISTOR, HIGH); closeRelay(); lcd_text("Tele off " ); } sleep(3); } }
int main(int argc, char* argv[]) { if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { cout << "HttpMsgServer " << endl; cout << "Server Build:" << __DATE__ << __TIME__ << endl; return ERR_SUCCESS; } signal(SIGPIPE, SIG_IGN); srand(time(NULL)); //日志类初始化 if (!Logger.Init(2000, 0, 0)){ cout <<"log init failed!!!"<< endl; return -1; } /* 设置打印级别 */ Logger.SetLogLevel(0x0040, true); Logger.Log(INFO, "The Server max files can open: %d ", getdtablesize()); CConfigFileReader* configFile = new CConfigFileReader("httpsvr.conf"); char* listenIp = configFile->GetConfigName("ListenIP"); char* strListenPort = configFile->GetConfigName("ListenPort"); char* strThreadNum = configFile->GetConfigName("ThreadNum"); //初始化数据库连接及管理类 CDBManager* pDBManager = CDBManager::getInstance(configFile); if (!pDBManager) { Logger.Log(ERROR, "DBManager init failed"); return ERR_FAILED; } pDBManager->Init(); if (!listenIp || !strListenPort) { Logger.Log(ERROR, "config file miss, exit "); return ERR_FAILED; } int ret = netlib_init(); if (ret == NETLIB_ERROR){ return ret; } uint16_t listenPort = atoi(strListenPort); CStrExplode listen_ip_list(listenIp, ';'); for (uint32_t i = 0; i < listen_ip_list.GetItemCnt(); i++) { ret = netlib_listen(listen_ip_list.GetItem(i), listenPort, HttpCallback, NULL); if (ret == NETLIB_ERROR) return ret; } cout << "server start listen on: " << listenIp << listenPort << endl; uint32_t threadNum = atoi(strThreadNum); InitHttpConn(threadNum);//初始化线程,增加心跳定时器 cout << "now enter the event loop!" << endl; writePid(); netlib_eventloop(); return 0; }
int main(int argc, char* argv[]) { if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { printf("Server Version: LoginServer/%s\n", VERSION); printf("Server Build: %s %s\n", __DATE__, __TIME__); return 0; } signal(SIGPIPE, SIG_IGN); CConfigFileReader config_file("loginserver.conf"); char* client_listen_ip = config_file.GetConfigName("ClientListenIP"); char* str_client_port = config_file.GetConfigName("ClientPort"); char* http_listen_ip = config_file.GetConfigName("HttpListenIP"); char* str_http_port = config_file.GetConfigName("HttpPort"); char* msg_server_listen_ip = config_file.GetConfigName("MsgServerListenIP"); char* str_msg_server_port = config_file.GetConfigName("MsgServerPort"); char* str_msfs_url = config_file.GetConfigName("msfs"); char* str_discovery = config_file.GetConfigName("discovery"); if (!msg_server_listen_ip || !str_msg_server_port || !http_listen_ip || !str_http_port || !str_msfs_url || !str_discovery) { log("config item missing, exit... "); return -1; } uint16_t client_port = atoi(str_client_port); uint16_t msg_server_port = atoi(str_msg_server_port); uint16_t http_port = atoi(str_http_port); strMsfsUrl = str_msfs_url; strDiscovery = str_discovery; pIpParser = new IpParser(); int ret = netlib_init(); if (ret == NETLIB_ERROR) return ret; CStrExplode client_listen_ip_list(client_listen_ip, ';'); for (uint32_t i = 0; i < client_listen_ip_list.GetItemCnt(); i++) { ret = netlib_listen(client_listen_ip_list.GetItem(i), client_port, client_callback, NULL); if (ret == NETLIB_ERROR) return ret; } CStrExplode msg_server_listen_ip_list(msg_server_listen_ip, ';'); for (uint32_t i = 0; i < msg_server_listen_ip_list.GetItemCnt(); i++) { ret = netlib_listen(msg_server_listen_ip_list.GetItem(i), msg_server_port, msg_serv_callback, NULL); if (ret == NETLIB_ERROR) return ret; } CStrExplode http_listen_ip_list(http_listen_ip, ';'); for (uint32_t i = 0; i < http_listen_ip_list.GetItemCnt(); i++) { ret = netlib_listen(http_listen_ip_list.GetItem(i), http_port, http_callback, NULL); if (ret == NETLIB_ERROR) return ret; } printf("server start listen on:\nFor client %s:%d\nFor MsgServer: %s:%d\nFor http:%s:%d\n", client_listen_ip, client_port, msg_server_listen_ip, msg_server_port, http_listen_ip, http_port); init_login_conn(); init_http_conn(); printf("now enter the event loop...\n"); writePid(); netlib_eventloop(); return 0; }
int main(int argc, char **argv) { int listenfd,connfd, port,clientlen; pid_t pid; struct sockaddr_in clientaddr; char isdaemon=0,*portp=NULL,*logp=NULL,tmpcwd[MAXLINE]; #ifdef HTTPS int sslport; char dossl=0,*sslportp=NULL; #endif openlog(argv[0],LOG_NDELAY|LOG_PID,LOG_DAEMON); cwd=(char*)get_current_dir_name(); strcpy(tmpcwd,cwd); strcat(tmpcwd,"/"); /* parse argv */ #ifdef HTTPS parse_option(argc,argv,&isdaemon,&portp,&logp,&sslportp,&dossl); sslportp==NULL ?(sslport=atoi(Getconfig("https"))) : (sslport=atoi(sslportp)); if(dossl==1||strcmp(Getconfig("dossl"),"yes")==0) dossl=1; #else parse_option(argc,argv,&isdaemon,&portp,&logp); #endif portp==NULL ?(port=atoi(Getconfig("http"))) : (port=atoi(portp)); Signal(SIGCHLD,sigChldHandler); /* init log */ if(logp==NULL) logp=Getconfig("log"); initlog(strcat(tmpcwd,logp)); /* whethe show dir */ if(strcmp(Getconfig("dir"),"no")==0) isShowdir=0; clientlen = sizeof(clientaddr); if(isdaemon==1||strcmp(Getconfig("daemon"),"yes")==0) Daemon(1,1); writePid(1); /* $https start */ #ifdef HTTPS if(dossl) { if((pid=Fork())==0) { listenfd= Open_listenfd(sslport); ssl_init(); while(1) { connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); if(access_ornot(inet_ntoa(clientaddr.sin_addr))==0) { clienterror(connfd,"maybe this web server not open to you!" , "403", "Forbidden", "Tiny couldn't read the file"); continue; } if((pid=Fork())>0) { Close(connfd); continue; } else if(pid==0) { ishttps=1; doit(connfd); exit(1); } } } } #endif /* $end https */ listenfd = Open_listenfd(port); while (1) { connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); if(access_ornot(inet_ntoa(clientaddr.sin_addr))==0) { clienterror(connfd,"maybe this web server not open to you!" , "403", "Forbidden", "Tiny couldn't read the file"); continue; } if((pid=Fork())>0) { Close(connfd); continue; } else if(pid==0) { doit(connfd); exit(1); } } }
int main(int argc, char* argv[]) { #if 0 pid_t pid = fork(); if (pid < 0) { exit(-1); } else if (pid > 0) { exit(0); } setsid(); #endif if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { printf("Server Version: FileServer/%s\n", VERSION); printf("Server Build: %s %s\n", __DATE__, __TIME__); return 0; } signal(SIGPIPE, SIG_IGN); // ¶ÁÈ¡ÅäÖÃÎļþ CConfigFileReader config_file("fileserver.conf"); char* str_client_listen_ip = config_file.GetConfigName("ClientListenIP"); char* str_client_listen_port = config_file.GetConfigName("ClientListenPort"); char* str_msg_server_listen_ip = config_file.GetConfigName("MsgServerListenIP"); char* str_msg_server_listen_port = config_file.GetConfigName("MsgServerListenPort"); char* str_task_timeout = config_file.GetConfigName("TaskTimeout"); if (!str_client_listen_ip || !str_client_listen_port || !str_msg_server_listen_ip || !str_msg_server_listen_port) { log("config item missing, exit... "); return -1; } uint16_t client_listen_port = atoi(str_client_listen_port); CStrExplode client_listen_ip_list(str_client_listen_ip, ';'); std::list<IM::BaseDefine::IpAddr> q; for (uint32_t i = 0; i < client_listen_ip_list.GetItemCnt(); i++) { ConfigUtil::GetInstance()->AddAddress(client_listen_ip_list.GetItem(i), client_listen_port); } uint16_t msg_server_listen_port = atoi(str_msg_server_listen_port); uint32_t task_timeout = atoi(str_task_timeout); ConfigUtil::GetInstance()->SetTaskTimeout(task_timeout); InitializeFileMsgServerConn(); InitializeFileClientConn(); int ret = netlib_init(); if (ret == NETLIB_ERROR) return ret; for (uint32_t i = 0; i < client_listen_ip_list.GetItemCnt(); i++) { // sokcet bind listen FileClientConnCallback ret = netlib_listen(client_listen_ip_list.GetItem(i), client_listen_port, FileClientConnCallback, NULL); if (ret == NETLIB_ERROR) { printf("listen %s:%d error!!\n", client_listen_ip_list.GetItem(i), client_listen_port); return ret; } else { printf("server start listen on %s:%d\n", client_listen_ip_list.GetItem(i), client_listen_port); } } // sokcet bind listen FileMsgServerConnCallback ret = netlib_listen(str_msg_server_listen_ip, msg_server_listen_port, FileMsgServerConnCallback, NULL); if (ret == NETLIB_ERROR) { printf("listen %s:%d error!!\n", str_msg_server_listen_ip, msg_server_listen_port); return ret; } else { printf("server start listen on %s:%d\n", str_msg_server_listen_ip, msg_server_listen_port); } printf("now enter the event loop...\n"); writePid(); netlib_eventloop(); printf("exiting.......\n"); log("exit"); return 0; }
int CPCD::Process::start() { /* We need to fork() twice, so that the second child (grandchild?) can * become a daemon. The original child then writes the pid file, * so that the monitor knows the pid of the new process, and then * exit()s. That way, the monitor process can pickup the pid, and * the running process is a daemon. * * This is a bit tricky but has the following advantages: * - the cpcd can die, and "reconnect" to the monitored clients * without restarting them. * - the cpcd does not have to wait() for the childs. init(1) will * take care of that. */ logger.info("Starting %d: %s", m_id, m_name.c_str()); m_status = STARTING; int pid = -1; switch(m_processType){ case TEMPORARY:{ #ifndef _WIN32 /** * Simple fork * don't ignore child */ switch(pid = fork()) { case 0: /* Child */ setsid(); writePid(getpgrp()); if(runas(m_runas.c_str()) == 0){ signal(SIGCHLD, SIG_DFL); do_exec(); } _exit(1); break; case -1: /* Error */ logger.error("Cannot fork: %s\n", strerror(errno)); m_status = STOPPED; return -1; break; default: /* Parent */ logger.debug("Started temporary %d : pid=%d", m_id, pid); break; } #else //_WIN32 do_exec(); #endif break; } #ifndef _WIN32 case PERMANENT:{ /** * PERMANENT */ switch(fork()) { case 0: /* Child */ signal(SIGCHLD, SIG_IGN); switch(pid = fork()) { case 0: /* Child */ setsid(); writePid(getpgrp()); if(runas(m_runas.c_str()) != 0){ _exit(1); } signal(SIGCHLD, SIG_DFL); do_exec(); _exit(1); /* NOTREACHED */ break; case -1: /* Error */ logger.error("Cannot fork: %s\n", strerror(errno)); writePid(-1); _exit(1); break; default: /* Parent */ logger.debug("Started permanent %d : pid=%d", m_id, pid); _exit(0); break; } break; case -1: /* Error */ logger.error("Cannot fork: %s\n", strerror(errno)); m_status = STOPPED; return -1; break; default: /* Parent */ break; } break; } #endif default: logger.critical("Unknown process type"); return -1; } while(readPid() < 0){ sched_yield(); } errno = 0; pid_t pgid = IF_WIN(-1, getpgid(pid)); if(pgid != -1 && pgid != m_pid){ logger.error("pgid and m_pid don't match: %d %d (%d)", pgid, m_pid, pid); } if(isRunning()){ m_status = RUNNING; return 0; } m_status = STOPPED; return -1; }
int main(int argc, char* argv[]) { if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { // printf("Server Version: MsgServer/%s\n", VERSION); printf("Server Build: %s %s\n", __DATE__, __TIME__); return 0; } signal(SIGPIPE, SIG_IGN); srand(time(NULL)); log("MsgServer max files can open: %d ", getdtablesize()); CConfigFileReader config_file("msgserver.conf"); char* listen_ip = config_file.GetConfigName("ListenIP"); char* str_listen_port = config_file.GetConfigName("ListenPort"); char* ip_addr1 = config_file.GetConfigName("IpAddr1"); // 电信IP char* ip_addr2 = config_file.GetConfigName("IpAddr2"); // 网通IP char* str_max_conn_cnt = config_file.GetConfigName("MaxConnCnt"); char* str_aes_key = config_file.GetConfigName("aesKey"); uint32_t db_server_count = 0; serv_info_t* db_server_list = read_server_config(&config_file, "DBServerIP", "DBServerPort", db_server_count); uint32_t login_server_count = 0; serv_info_t* login_server_list = read_server_config(&config_file, "LoginServerIP", "LoginServerPort", login_server_count); uint32_t route_server_count = 0; serv_info_t* route_server_list = read_server_config(&config_file, "RouteServerIP", "RouteServerPort", route_server_count); uint32_t push_server_count = 0; serv_info_t* push_server_list = read_server_config(&config_file, "PushServerIP", "PushServerPort", push_server_count); uint32_t file_server_count = 0; serv_info_t* file_server_list = read_server_config(&config_file, "FileServerIP", "FileServerPort", file_server_count); if (!str_aes_key || strlen(str_aes_key)!=32) { log("aes key is invalied"); return -1; } pAes = new CAes(str_aes_key); // 必须至少配置2个BusinessServer实例, 一个用于用户登录业务,一个用于其他业务 // 这样当其他业务量非常繁忙时,也不会影响客服端的登录验证 // 建议配置4个实例,这样更新BusinessServer时,不会影响业务 if (db_server_count < 2) { log("DBServerIP need 2 instance at lest "); return 1; } // 到BusinessServer的开多个并发的连接 uint32_t concurrent_db_conn_cnt = DEFAULT_CONCURRENT_DB_CONN_CNT; uint32_t db_server_count2 = db_server_count * DEFAULT_CONCURRENT_DB_CONN_CNT; char* concurrent_db_conn = config_file.GetConfigName("ConcurrentDBConnCnt"); if (concurrent_db_conn) { concurrent_db_conn_cnt = atoi(concurrent_db_conn); db_server_count2 = db_server_count * concurrent_db_conn_cnt; } serv_info_t* db_server_list2 = new serv_info_t [ db_server_count2]; for (uint32_t i = 0; i < db_server_count2; i++) { db_server_list2[i].server_ip = db_server_list[i / concurrent_db_conn_cnt].server_ip.c_str(); db_server_list2[i].server_port = db_server_list[i / concurrent_db_conn_cnt].server_port; } if (!listen_ip || !str_listen_port || !ip_addr1) { log("config file miss, exit... "); return -1; } // 没有IP2,就用第一个IP if (!ip_addr2) { ip_addr2 = ip_addr1; } uint16_t listen_port = atoi(str_listen_port); uint32_t max_conn_cnt = atoi(str_max_conn_cnt); int ret = netlib_init(); if (ret == NETLIB_ERROR) return ret; CStrExplode listen_ip_list(listen_ip, ';'); for (uint32_t i = 0; i < listen_ip_list.GetItemCnt(); i++) { ret = netlib_listen(listen_ip_list.GetItem(i), listen_port, msg_serv_callback, NULL); if (ret == NETLIB_ERROR) return ret; } printf("server start listen on: %s:%d\n", listen_ip, listen_port); init_msg_conn(); init_file_serv_conn(file_server_list, file_server_count); init_db_serv_conn(db_server_list2, db_server_count2, concurrent_db_conn_cnt); init_login_serv_conn(login_server_list, login_server_count, ip_addr1, ip_addr2, listen_port, max_conn_cnt); init_route_serv_conn(route_server_list, route_server_count); init_push_serv_conn(push_server_list, push_server_count); printf("now enter the event loop...\n"); writePid(); netlib_eventloop(); return 0; }