Пример #1
0
/* main - slurmctld main function, start various threads and process RPCs */
int main(int argc, char *argv[])
{
	pthread_attr_t thread_attr;
	char node_name[128];
	void *db_conn = NULL;
	assoc_init_args_t assoc_init_arg;

	_init_config();
	log_init(argv[0], log_opts, LOG_DAEMON, NULL);
	if (read_slurmdbd_conf())
		exit(1);
	_parse_commandline(argc, argv);
	_update_logging(true);
	_update_nice();

	if (slurm_auth_init(NULL) != SLURM_SUCCESS) {
		fatal("Unable to initialize %s authentication plugin",
		      slurmdbd_conf->auth_type);
	}
	if (slurm_acct_storage_init(NULL) != SLURM_SUCCESS) {
		fatal("Unable to initialize %s accounting storage plugin",
		      slurmdbd_conf->storage_type);
	}
	_kill_old_slurmdbd();
	if (foreground == 0)
		_daemonize();

	/*
	 * Need to create pidfile here in case we setuid() below
	 * (init_pidfile() exits if it can't initialize pid file).
	 * On Linux we also need to make this setuid job explicitly
	 * able to write a core dump.
	 * This also has to happen after daemon(), which closes all fd's,
	 * so we keep the write lock of the pidfile.
	 */
	_init_pidfile();
	_become_slurm_user();
	if (foreground == 0)
		_set_work_dir();
	log_config();

#ifdef PR_SET_DUMPABLE
	if (prctl(PR_SET_DUMPABLE, 1) < 0)
		debug ("Unable to set dumpable to 1");
#endif /* PR_SET_DUMPABLE */

	if (xsignal_block(dbd_sigarray) < 0)
		error("Unable to block signals");

	/* Create attached thread for signal handling */
	slurm_attr_init(&thread_attr);
	if (pthread_create(&signal_handler_thread, &thread_attr,
			   _signal_handler, NULL))
		fatal("pthread_create %m");
	slurm_attr_destroy(&thread_attr);

	registered_clusters = list_create(NULL);

	slurm_attr_init(&thread_attr);
	if (pthread_create(&commit_handler_thread, &thread_attr,
			   _commit_handler, NULL))
		fatal("pthread_create %m");
	slurm_attr_destroy(&thread_attr);

	memset(&assoc_init_arg, 0, sizeof(assoc_init_args_t));

	/* If we are tacking wckey we need to cache
	   wckeys, if we aren't only cache the users, qos */
	assoc_init_arg.cache_level = ASSOC_MGR_CACHE_USER | ASSOC_MGR_CACHE_QOS;
	if (slurmdbd_conf->track_wckey)
		assoc_init_arg.cache_level |= ASSOC_MGR_CACHE_WCKEY;

	db_conn = acct_storage_g_get_connection(NULL, 0, true, NULL);
	if (assoc_mgr_init(db_conn, &assoc_init_arg, errno) == SLURM_ERROR) {
		error("Problem getting cache of data");
		acct_storage_g_close_connection(&db_conn);
		goto end_it;
	}

	if (gethostname_short(node_name, sizeof(node_name)))
		fatal("getnodename: %m");

	while (1) {
		if (slurmdbd_conf->dbd_backup &&
		    (!strcmp(node_name, slurmdbd_conf->dbd_backup) ||
		     !strcmp(slurmdbd_conf->dbd_backup, "localhost"))) {
			info("slurmdbd running in background mode");
			have_control = false;
			backup = true;
			/* make sure any locks are released */
			acct_storage_g_commit(db_conn, 1);
			run_dbd_backup();
			if (!shutdown_time)
				assoc_mgr_refresh_lists(db_conn);
		} else if (slurmdbd_conf->dbd_host &&
			   (!strcmp(slurmdbd_conf->dbd_host, node_name) ||
			    !strcmp(slurmdbd_conf->dbd_host, "localhost"))) {
			backup = false;
			have_control = true;
		} else {
			fatal("This host not configured to run SlurmDBD "
			      "(%s != %s | (backup) %s)",
			      node_name, slurmdbd_conf->dbd_host,
			      slurmdbd_conf->dbd_backup);
		}

		if (!shutdown_time) {
			/* Create attached thread to process incoming RPCs */
			slurm_attr_init(&thread_attr);
			if (pthread_create(&rpc_handler_thread, &thread_attr,
					   rpc_mgr, NULL))
				fatal("pthread_create error %m");
			slurm_attr_destroy(&thread_attr);
		}

		if (!shutdown_time) {
			/* Create attached thread to do usage rollup */
			slurm_attr_init(&thread_attr);
			if (pthread_create(&rollup_handler_thread,
					   &thread_attr,
					   _rollup_handler, db_conn))
				fatal("pthread_create error %m");
			slurm_attr_destroy(&thread_attr);
		}

		/* Daemon is fully operational here */
		if (!shutdown_time || primary_resumed) {
			shutdown_time = 0;
			info("slurmdbd version %s started",
			     SLURM_VERSION_STRING);
			if (backup)
				run_dbd_backup();
		}

		_request_registrations(db_conn);
		acct_storage_g_commit(db_conn, 1);

		/* this is only ran if not backup */
		if (rollup_handler_thread)
			pthread_join(rollup_handler_thread, NULL);
		if (rpc_handler_thread)
			pthread_join(rpc_handler_thread, NULL);

		if (backup && primary_resumed) {
			shutdown_time = 0;
			info("Backup has given up control");
		}

		if (shutdown_time)
			break;
	}
	/* Daemon termination handled here */

end_it:

	if (signal_handler_thread)
		pthread_join(signal_handler_thread, NULL);
	if (commit_handler_thread)
		pthread_join(commit_handler_thread, NULL);

	acct_storage_g_commit(db_conn, 1);
	acct_storage_g_close_connection(&db_conn);

	if (slurmdbd_conf->pid_file &&
	    (unlink(slurmdbd_conf->pid_file) < 0)) {
		verbose("Unable to remove pidfile '%s': %m",
			slurmdbd_conf->pid_file);
	}

	FREE_NULL_LIST(registered_clusters);

	assoc_mgr_fini(NULL);
	slurm_acct_storage_fini();
	slurm_auth_fini();
	log_fini();
	free_slurmdbd_conf();
	exit(0);
}
Пример #2
0
static void
_service_run (srvmode_t mode, int rfdno, int wfdno)
{
    List l = diod_conf_get_listen ();
    int nwthreads = diod_conf_get_nwthreads ();
    int flags = diod_conf_get_debuglevel ();
    uid_t euid = geteuid ();
    int n;

    ss.mode = mode;
    ss.rfdno = rfdno;
    ss.wfdno = wfdno;
    ss.shutdown = 0;
    ss.reload = 0;
    _service_sigsetup ();

    ss.fds = NULL;
    ss.nfds = 0;
    switch (mode) {
        case SRV_FILEDES:
            break;
        case SRV_NORMAL:
        case SRV_SOCKTEST:
            if (!diod_sock_listen (l, &ss.fds, &ss.nfds))
                msg_exit ("failed to set up listener");
#if WITH_RDMATRANS
            ss.rdma = diod_rdma_create ();
            diod_rdma_listen (ss.rdma);
#endif
            break;
    }

    /* manipulate squash/runas users if not root */
    if (euid != 0) {
        if (diod_conf_get_allsquash ()) {
            struct passwd *pw = getpwuid (euid);
            char *su = diod_conf_get_squashuser ();
            if (!pw)
                msg_exit ("getpwuid on effective uid failed");
            if (strcmp (pw->pw_name, su) != 0) {
                if (strcmp (su, DFLT_SQUASHUSER) != 0)
                    msg ("changing squashuser '%s' to '%s' "
                         "since you are not root", su, pw->pw_name);
                diod_conf_set_squashuser (pw->pw_name); /* fixes issue 41 */
            }
        } else { /* N.B. runasuser cannot be set in the config file */
            uid_t ruid = diod_conf_get_runasuid ();
            if (diod_conf_opt_runasuid () && ruid != euid)
                msg ("changing runasuid %d to %d "
                     "since you are not root", ruid, euid);
            diod_conf_set_runasuid (euid);
        }
    }
        
    if (!diod_conf_get_foreground () && mode != SRV_FILEDES)
        _daemonize (); /* implicit fork - no pthreads before this */
    if (!diod_conf_get_foreground () && mode != SRV_FILEDES)
        diod_log_set_dest (diod_conf_get_logdest ());

    /* drop root */
    if (euid == 0) {
        if (diod_conf_get_allsquash ())
            _become_user (diod_conf_get_squashuser (), -1, 1);
        else if (diod_conf_opt_runasuid ())
            _become_user (NULL, diod_conf_get_runasuid (), 1);
    }

    /* clear umask */
    umask (0);

    flags |= SRV_FLAGS_LOOSEFID;        /* work around buggy clients */
    flags |= SRV_FLAGS_AUTHCONN;
    //flags |= SRV_FLAGS_FLUSHSIG;      /* XXX temporarily off */
    if (geteuid () == 0) {
        flags |= SRV_FLAGS_SETFSID;
        flags |= SRV_FLAGS_DAC_BYPASS;
        if (_test_setgroups ())
            flags |= SRV_FLAGS_SETGROUPS;
        else
            msg ("test_setgroups: groups are per-process (disabling)");
    }

    /* Process dumpable flag may have been cleared by uid manipulation above.
     * Set it here, then maintain it in user.c::np_setfsid () as uids are
     * further manipulated.
     */
    if (prctl (PR_SET_DUMPABLE, 1, 0, 0, 0) < 0)
        err_exit ("prctl PR_SET_DUMPABLE failed");

    if (!diod_conf_get_userdb ())
        flags |= SRV_FLAGS_NOUSERDB;
    if (!(ss.srv = np_srv_create (nwthreads, flags))) /* starts threads */
        errn_exit (np_rerror (), "np_srv_create");
    if (diod_init (ss.srv) < 0)
        errn_exit (np_rerror (), "diod_init");

    if ((n = pthread_create (&ss.t, NULL, _service_loop, NULL)))
        errn_exit (n, "pthread_create _service_loop");
#if WITH_RDMATRANS
    if ((n = pthread_create (&ss.rdma_t, NULL, _service_loop_rdma, NULL)))
        errn_exit (n, "pthread_create _service_loop_rdma");
#endif
    switch (mode) {
        case SRV_FILEDES:
        case SRV_SOCKTEST:
            np_srv_wait_conncount (ss.srv, 1);
            pthread_kill (ss.t, SIGUSR1);
            break;
        case SRV_NORMAL:
            break;
    }
    if ((n = pthread_join (ss.t, NULL)))
        errn_exit (n, "pthread_join _service_loop");
#if WITH_RDMATRANS
    if ((n = pthread_join (ss.rdma_t, NULL)))
        errn_exit (n, "pthread_join _service_loop_rdma");
#endif

    diod_fini (ss.srv);
    np_srv_destroy (ss.srv);
}
Пример #3
0
/* Main Entry Point for this Daemon */
extern int main (int argc, char *argv[])
{
	sigset_t   signal_set;
	GMainLoop *main_loop  = NULL;
	GError    *gerror     = NULL;
	GThread   *sig_thread = NULL;
	GOptionContext *context = NULL;
	gpointer   trc = NULL;

	uid_t     real_user_id = 0;
	uid_t     effective_user_id = 0;
	gint      rc = 0;
	struct    passwd *userinfo = NULL;

	/* initialize threading and mainloop */
	g_type_init();
	main_loop = g_main_loop_new (NULL, FALSE);

	/* handle command line arguments */
	if ((rc = _handle_command_line( argc, argv, &context)) != EXIT_SUCCESS) {
		g_main_loop_unref (main_loop);
		exit (rc);
	}

	/* remember real and effective userid to restore them on shutdown */
	real_user_id = getuid ();
	if (gd_pch_effective_userid != NULL) {
		userinfo = getpwnam(gd_pch_effective_userid);
		effective_user_id = userinfo->pw_uid;
	}
	else {
		effective_user_id = geteuid();
		userinfo = getpwuid(effective_user_id);
		gd_pch_effective_userid = userinfo->pw_name;
	}

	g_message("%s-%s is in startup mode as user(%s)",
		PACKAGE_NAME, PACKAGE_VERSION, gd_pch_effective_userid);

	/* daemonize */
	if (!i_debug) {
		switch (_daemonize(gd_pch_pid_filename)) {
		case EXIT_SUCCESS:  /* grandchild */
			break;
		case EXIT_ERROR:    /* any error */
			exit (EXIT_FAILURE);
			break;
		default:            /* parent or child pids */
			exit (EXIT_SUCCESS);
			break;
		}
	}
	else {
		g_message("Skipping daemonizing process");
	}

	/* become the requested user */
	seteuid (effective_user_id);

	if (!i_debug) {
		/* block all signals */
		sigfillset (&signal_set);
		pthread_sigmask (SIG_BLOCK, &signal_set, NULL);

		/* create the signal handling thread */
		sig_thread = g_thread_create ((GThreadFunc)_thread_handle_signals,
				main_loop, TRUE, &gerror);
		if (gerror != NULL) {
			g_message("Create signal thread failed: %s", gerror->message);
			g_error_free(gerror);
			g_option_context_free(context);
			g_main_loop_unref (main_loop);
			exit (EXIT_FAILURE);
		}
	}

	_load_config();

	if (!phonefsod_dbus_setup()) {
		g_option_context_free(context);
		g_main_loop_unref(main_loop);
		exit(EXIT_FAILURE);
	}


	//notify = inotify_init();
	//inotify_add_watch(notify, PHONEFSOD_CONFIG, IN_MODIFY);

	/* Start glib main loop and run list_resources() */
	g_debug("entering glib main loop");
	g_timeout_add_seconds(1, fso_startup, NULL);
	g_main_loop_run(main_loop);

	phonefsod_dbus_shutdown();

	/* Cleanup and exit */
	if (!i_debug) {
		trc = g_thread_join(sig_thread);
		g_message("Signal thread was ended by a %s signal.",
				g_strsignal(GPOINTER_TO_INT(trc)) );

		pthread_sigmask (SIG_UNBLOCK, &signal_set, NULL);
		g_option_context_free (context);
	}
	g_main_loop_unref (main_loop);

//	if (incoming_calls)
//		free(incoming_calls);
//	if (outgoing_calls)
//		free(outgoing_calls);
	if (sim_pin)
		free(sim_pin);
	if (pdp_apn)
		free(pdp_apn);
	if (pdp_user)
		free(pdp_user);
	if (pdp_password)
		free(pdp_password);

	/* become the privledged user again */
	seteuid (real_user_id);

	/* Remove the PID File to show we are inactive */
	if (!i_debug) {
		if (g_unlink(gd_pch_pid_filename) != 0) {
			g_warning("Main Error: cannot unlink/remove pidfile %s: %s",
					gd_pch_pid_filename, strerror(errno));
		}
	}

	/* write shutdown messages */
	g_message("%s-%s clean shutdown", PACKAGE_NAME, PACKAGE_VERSION);

	exit (EXIT_SUCCESS);
}
Пример #4
0
int main(int argc, char * argv[]) 
{
    extern char* optarg;
    
    

    // on write, don't send signal for SIGPIPE, just set errno to EPIPE
    // and return -1
    //signal is a deprecated and potentially dangerous function
    //(void) ::signal(SIGPIPE, SIG_IGN);
    struct sigaction act;
    
#if defined(sun) || defined(i386) || defined(__x86_64__) || defined (__MacOSX__) || defined(__powerpc__) || defined (__osf__) || defined (__sgi_cc__) || defined (__hpux__) || defined (__linux__)
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    act.sa_handler = (void(*)(int))&sigcatcher;
#elif defined(__sgi__) 
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	act.sa_handler = (void(*)(...))&sigcatcher;
#else
    act.sa_mask = 0;
    act.sa_flags = 0;
    act.sa_handler = (void(*)(...))&sigcatcher;
#endif
    (void)::sigaction(SIGPIPE, &act, NULL);
    (void)::sigaction(SIGHUP, &act, NULL);
    (void)::sigaction(SIGINT, &act, NULL);
    (void)::sigaction(SIGTERM, &act, NULL);
    (void)::sigaction(SIGQUIT, &act, NULL);
    (void)::sigaction(SIGALRM, &act, NULL);


#if __solaris__ || __linux__ || __hpux__
    //grow our pool of file descriptors to the max!
    struct rlimit rl;
    
    // set it to the absolute maximum that the operating system allows - have to be superuser to do this
    rl.rlim_cur = RLIM_INFINITY;
    rl.rlim_max = RLIM_INFINITY;
 
    setrlimit (RLIMIT_NOFILE, &rl);
#endif

#if __MacOSX__
    struct rlimit rl;
    getrlimit(RLIMIT_NOFILE,  &rl); //get the default values
    //printf("current open file limit =%"_U32BITARG_"\n", (UInt32) rl.rlim_cur); //leopard returns  256
    //printf("current open file max =%"_U32BITARG_"\n", (UInt32) rl.rlim_max);//leopard returns infinity (-1)
    
    rl. rlim_max = (rlim_t) RLIM_INFINITY -1; //use a big number to find out the real max but do not use RLIM_INFINITY that is not allowed. see man page
    setrlimit (RLIMIT_NOFILE, &rl); //resets the max value stored by limits to the boot config values.
    getrlimit(RLIMIT_NOFILE,  &rl); //now get the real max value
    //printf("current open file limit =%"_U32BITARG_"\n", (UInt32) rl.rlim_cur);
    //printf("current open file max =%"_U32BITARG_"\n", (UInt32) rl.rlim_max);
    
    rl.rlim_cur = (rlim_t) ( (float) rl.rlim_max * 0.9);   //use 90% of the max set in /etc/rc.server and /etc/sysctl.conf.default
    setrlimit (RLIMIT_NOFILE, &rl);  //finally set the current limit 
    
#endif
    
#if 0 // testing
    getrlimit(RLIMIT_NOFILE,  &rl);
    printf("current open file limit =%"_U32BITARG_"\n", (UInt32) rl.rlim_cur);
    printf("current open file max =%"_U32BITARG_"\n", (UInt32) rl.rlim_max);
#endif

#if __MacOSX__ || __FreeBSD__
        //
        // These 2 OSes have problems with large socket buffer sizes. Make sure they allow even
        // ridiculously large ones, because we may need them to receive a large volume of ACK packets
        // from the client
        
        //
        // We raise the limit imposed by the kernel by calling the sysctl system call.
        int mib[CTL_MAXNAME];
        mib[0] = CTL_KERN;
        mib[1] = KERN_IPC;
        mib[2] = KIPC_MAXSOCKBUF;
        mib[3] = 0;

        int maxSocketBufferSizeVal = 2000 * 1024; // Allow up to 2 MB. That is WAY more than we should need
        (void) ::sysctl(mib, 3, 0, 0, &maxSocketBufferSizeVal, sizeof(maxSocketBufferSizeVal));
        //int sysctlErr =  ::sysctl(mib, 3, 0, 0, &maxSocketBufferSizeVal, sizeof(maxSocketBufferSizeVal));
        //qtss_printf("sysctl maxSocketBufferSizeVal=%d err=%d\n",maxSocketBufferSizeVal, sysctlErr);
 #endif
    
    //First thing to do is to read command-line arguments.
    int ch;
    int thePort = 0; //port can be set on the command line
    int statsUpdateInterval = 0;
    QTSS_ServerState theInitialState = qtssRunningState;
    
    Bool16 dontFork = false;
    Bool16 theXMLPrefsExist = true;
    UInt32 debugLevel = 0;
    UInt32 debugOptions = kRunServerDebug_Off;
	static char* sDefaultConfigFilePath = DEFAULTPATHS_ETC_DIR_OLD "easydarwin.conf";
	static char* sDefaultXMLFilePath = DEFAULTPATHS_ETC_DIR "easydarwin.xml";

    char* theConfigFilePath = sDefaultConfigFilePath;
    char* theXMLFilePath = sDefaultXMLFilePath;
    while ((ch = getopt(argc,argv, "vdfxp:DZ:c:o:S:Ih")) != EOF) // opt: means requires option arg
    {
        switch(ch)
        {
            case 'v':
                usage();
                ::exit(0);  
            case 'd':
                dontFork = RunInForeground();
                
                break;                
            case 'D':
               dontFork = RunInForeground();

               debugOptions |= kRunServerDebugDisplay_On;
                
               if (debugLevel == 0)
                    debugLevel = 1;
                    
               if (statsUpdateInterval == 0)
                    statsUpdateInterval = 3;
                    
               break;            
            case 'Z':
                Assert(optarg != NULL);// this means we didn't declare getopt options correctly or there is a bug in getopt.
                debugLevel = (UInt32) ::atoi(optarg);
                                
                break;
            case 'f':
				theXMLFilePath  = DEFAULTPATHS_ETC_DIR "easydarwin.xml";
                break;
            case 'p':
                Assert(optarg != NULL);// this means we didn't declare getopt options correctly or there is a bug in getopt.
                thePort = ::atoi(optarg);
                break;
            case 'S':
                dontFork = RunInForeground();
                Assert(optarg != NULL);// this means we didn't declare getopt options correctly or there is a bug in getopt.
                statsUpdateInterval = ::atoi(optarg);
                break;
            case 'c':
                Assert(optarg != NULL);// this means we didn't declare getopt options correctly or there is a bug in getopt.
                theXMLFilePath = optarg;
                break;
            case 'o':
                Assert(optarg != NULL);// this means we didn't declare getopt options correctly or there is a bug in getopt.
                theConfigFilePath = optarg;
                break;
            case 'x':
                theXMLPrefsExist = false; // Force us to generate a new XML prefs file
                theInitialState = qtssShuttingDownState;
                dontFork = true;
                break;
            case 'I':
                theInitialState = qtssIdleState;
                break;
            case 'h':
                usage();
                ::exit(0);
            default:
                break;
        }
    }
    
  
    // Check port
    if (thePort < 0 || thePort > 65535)
    { 
        qtss_printf("Invalid port value = %d max value = 65535\n",thePort);
        exit (-1);
    }

    // Check expiration date
    QTSSExpirationDate::PrintExpirationDate();
    if (QTSSExpirationDate::IsSoftwareExpired())
    {
        qtss_printf("Streaming Server has expired\n");
        ::exit(0);
    }


    XMLPrefsParser theXMLParser(theXMLFilePath);
    
    //
    // Check to see if the XML file exists as a directory. If it does,
    // just bail because we do not want to overwrite a directory
    if (theXMLParser.DoesFileExistAsDirectory())
    {
        qtss_printf("Directory located at location where streaming server prefs file should be.\n");
        exit(-1);
    }
    
    //
    // Check to see if we can write to the file
    if (!theXMLParser.CanWriteFile())
    {
        qtss_printf("Cannot write to the streaming server prefs file.\n");
        exit(-1);
    }

    // If we aren't forced to create a new XML prefs file, whether
    // we do or not depends solely on whether the XML prefs file exists currently.
    if (theXMLPrefsExist)
        theXMLPrefsExist = theXMLParser.DoesFileExist();
    
    if (!theXMLPrefsExist)
    {
        
        //
        // The XML prefs file doesn't exist, so let's create an old-style
        // prefs source in order to generate a fresh XML prefs file.
        
        if (theConfigFilePath != NULL)
        {   
            FilePrefsSource* filePrefsSource = new FilePrefsSource(true); // Allow dups
            
            if ( filePrefsSource->InitFromConfigFile(theConfigFilePath) )
            { 
               qtss_printf("Generating a new prefs file at %s\n", theXMLFilePath);
            }

            if (GenerateAllXMLPrefs(filePrefsSource, &theXMLParser))
            {
                qtss_printf("Fatal Error: Could not create new prefs file at: %s. (%d)\n", theXMLFilePath, OSThread::GetErrno());
                ::exit(-1);
            }
        }
    }

 
    //
    // Parse the configs from the XML file
    int xmlParseErr = theXMLParser.Parse();
    if (xmlParseErr)
    {
        qtss_printf("Fatal Error: Could not load configuration file at %s. (%d)\n", theXMLFilePath, OSThread::GetErrno());
        ::exit(-1);
    }
    
    //Unless the command line option is set, fork & daemonize the process at this point
    if (!dontFork)
    {
#ifdef __sgi__
		// for some reason, this method doesn't work right on IRIX 6.4 unless the first arg
		// is _DF_NOFORK.  if the first arg is 0 (as it should be) the result is a server
		// that is essentially paralized and doesn't respond to much at all.  So for now,
		// leave the first arg as _DF_NOFORK
//		if (_daemonize(_DF_NOFORK, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO) != 0)
        if (_daemonize(0, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO) != 0)
#else
        if (daemon(0,0) != 0)
#endif
        {
#if DEBUG
            qtss_printf("Failed to daemonize process. Error = %d\n", OSThread::GetErrno());
#endif
            exit(-1);
        }
    }
    
    //Construct a Prefs Source object to get server text messages
    FilePrefsSource theMessagesSource;
    theMessagesSource.InitFromConfigFile("qtssmessages.txt");
    

    int status = 0;
    int pid = 0;
    pid_t processID = 0;
	
    if ( !dontFork) // if (fork) 
    {
        //loop until the server exits normally. If the server doesn't exit
        //normally, then restart it.
        // normal exit means the following
        // the child quit 
        do // fork at least once but stop on the status conditions returned by wait or if autoStart pref is false
        {
            processID = fork();
            Assert(processID >= 0);
            if (processID > 0) // this is the parent and we have a child
            {
                sChildPID = processID;
                status = 0;
                while (status == 0) //loop on wait until status is != 0;
                {	
                 	pid =::wait(&status);
                 	SInt8 exitStatus = (SInt8) WEXITSTATUS(status);
                	//qtss_printf("Child Process %d wait exited with pid=%d status=%d exit status=%d\n", processID, pid, status, exitStatus);
                	
					if (WIFEXITED(status) && pid > 0 && status != 0) // child exited with status -2 restart or -1 don't restart 
					{
						//qtss_printf("child exited with status=%d\n", exitStatus);
						
						if ( exitStatus == -1) // child couldn't run don't try again
						{
							qtss_printf("child exited with -1 fatal error so parent is exiting too.\n");
							exit (EXIT_FAILURE); 
						}
						break; // restart the child
							
					}
					
					if (WIFSIGNALED(status)) // child exited on an unhandled signal (maybe a bus error or seg fault)
					{	
						//qtss_printf("child was signalled\n");
						break; // restart the child
					}

                 		
                	if (pid == -1 && status == 0) // parent woken up by a handled signal
                   	{
						//qtss_printf("handled signal continue waiting\n");
                   		continue;
                   	}
                   	
                 	if (pid > 0 && status == 0)
                 	{
                 		//qtss_printf("child exited cleanly so parent is exiting\n");
                 		exit(EXIT_SUCCESS);                		
                	}
                	
                	//qtss_printf("child died for unknown reasons parent is exiting\n");
                	exit (EXIT_FAILURE);
                }
            }
            else if (processID == 0) // must be the child
				break;
            else
            	exit(EXIT_FAILURE);
            	
            	
            //eek. If you auto-restart too fast, you might start the new one before the OS has
            //cleaned up from the old one, resulting in startup errors when you create the new
            //one. Waiting for a second seems to work
            sleep(1);
        } while (RestartServer(theXMLFilePath)); // fork again based on pref if server dies
        if (processID != 0) //the parent is quitting
        	exit(EXIT_SUCCESS);   

        
    }
    sChildPID = 0;
    //we have to do this again for the child process, because sigaction states
    //do not span multiple processes.
    (void)::sigaction(SIGPIPE, &act, NULL);
    (void)::sigaction(SIGHUP, &act, NULL);
    (void)::sigaction(SIGINT, &act, NULL);
    (void)::sigaction(SIGTERM, &act, NULL);
    (void)::sigaction(SIGQUIT, &act, NULL);

#ifdef __hpux__  
	// Set Priority Type to Real Time, timeslice = 100 milliseconds. Change the timeslice upwards as needed. This keeps the server priority above the playlist broadcaster which is a time-share scheduling type.
	char commandStr[64];
	qtss_sprintf(commandStr, "/usr/bin/rtprio -t -%d", (int) getpid()); 
#if DEBUG
	qtss_printf("setting priority to Real Time: %s\n", commandStr);
#endif
	(void) ::system(commandStr);    
#endif
    
#ifdef __solaris__  
    // Set Priority Type to Real Time, timeslice = 100 milliseconds. Change the timeslice upwards as needed. This keeps the server priority above the playlist broadcaster which is a time-share scheduling type.
    char commandStr[64];
    qtss_sprintf(commandStr, "priocntl -s -c RT -t 10 -i pid %d", (int) getpid()); 
    (void) ::system(commandStr);    
#endif

#ifdef __MacOSX__
    (void) ::umask(S_IWGRP|S_IWOTH); // make sure files are opened with default of owner -rw-r-r-
#endif

    //This function starts, runs, and shuts down the server
    if (::StartServer(&theXMLParser, &theMessagesSource, thePort, statsUpdateInterval, theInitialState, dontFork, debugLevel, debugOptions) != qtssFatalErrorState)
    {    ::RunServer();
         CleanPid(false);
         exit (EXIT_SUCCESS);
    }
    else
    	exit(-1); //Cant start server don't try again
}
Пример #5
0
int
main(int argc, const char *argv[])
{
    header();

    uint16_t port = PORT_NUMBER;
    uint16_t configurationPort = 2001;
    bool daemon = false;
    int capacity = -1;
    const char *configFileName = NULL;

    char *logfile = NULL;

    if (argc == 2 && strcasecmp(argv[1], "-h") == 0) {
        _usage(EXIT_SUCCESS);
    }

    int logLevelArray[MetisLoggerFacility_END];
    for (int i = 0; i < MetisLoggerFacility_END; i++) {
        logLevelArray[i] = -1;
    }

    for (int i = 0; i < argc; i++) {
        if (argv[i][0] == '-') {
            if (strcmp(argv[i], "--config") == 0) {
                configFileName = argv[i + 1];
                i++;
            } else if (strcmp(argv[i], "--port") == 0) {
                port = atoi(argv[i + 1]);
                i++;
            } else if (strcmp(argv[i], "--daemon") == 0) {
                daemon = true;
            } else if (strcmp(argv[i], "--capacity") == 0 || strcmp(argv[i], "-c") == 0) {
                capacity = atoi(argv[i + 1]);
                i++;
            } else if (strcmp(argv[i], "--log") == 0) {
                _setLogLevel(logLevelArray, argv[i + 1]);
                i++;
            } else if (strcmp(argv[i], "--log-file") == 0) {
                if (logfile) {
                    // error cannot repeat
                    fprintf(stderr, "Cannot specify --log-file more than once\n");
                    _usage(EXIT_FAILURE);
                }

                logfile = parcMemory_StringDuplicate(argv[i + 1], strlen(argv[i + 1]));
                i++;
            } else {
                _usage(EXIT_FAILURE);
            }
        }
    }

    // set restrictive umask, in case we create any files
    umask(027);

    if (daemon && (logfile == NULL)) {
        fprintf(stderr, "Must specify a logfile when running in daemon mode\n");
        _usage(EXIT_FAILURE);
    }

    if (daemon) {
        // inside this call, parent will EXIT_SUCCESS and child will continue
        _daemonize();
    }

    MetisLogger *logger = NULL;
    if (logfile) {
        logger = _createLogfile(logfile);
        parcMemory_Deallocate((void **) &logfile);
    } else {
        PARCLogReporter *stdoutReporter = parcLogReporterTextStdout_Create();
        logger = metisLogger_Create(stdoutReporter, parcClock_Wallclock());
        parcLogReporter_Release(&stdoutReporter);
    }

    for (int i = 0; i < MetisLoggerFacility_END; i++) {
        if (logLevelArray[i] > -1) {
            metisLogger_SetLogLevel(logger, i, logLevelArray[i]);
        }
    }


    // this will update the clock to the tick clock
    MetisForwarder *metis = metisForwarder_Create(logger);

    MetisConfiguration *configuration = metisForwarder_GetConfiguration(metis);

    if (capacity > -1) {
        metisConfiguration_SetObjectStoreSize(configuration, capacity);
    }

    metisConfiguration_StartCLI(configuration, configurationPort);

    if (configFileName) {
        metisForwarder_SetupFromConfigFile(metis, configFileName);
    } else {
        // NULL to not setup AF_UNIX
        metisForwarder_SetupAllListeners(metis, port, NULL);
    }

    MetisDispatcher *dispatcher = metisForwarder_GetDispatcher(metis);

    metisLogger_Log(logger, MetisLoggerFacility_Core, PARCLogLevel_Alert, "daemon", "metis running port %d configuration-port %d", port, configurationPort);

    metisDispatcher_Run(dispatcher);

    metisLogger_Log(logger, MetisLoggerFacility_Core, PARCLogLevel_Alert, "daemon", "metis exiting port %d", port);

    metisForwarder_Destroy(&metis);

    sleep(2);

    metisLogger_Release(&logger);
    return 0;
}
Пример #6
0
int main(int argc, char *argv[]) {
	int status = 0;

	_log_init();

	_config_default_init();

	_cmdline_process(argc, argv);

	if (setregid(config.gid, config.gid) < 0)
		_failure("setregid");

	if (setreuid(config.uid, config.uid) < 0)
		_failure("setreuid");

	if (_signal_init() < 0)
		_failure("_signal_init");

	if (_daemonize() < 0)
		_failure("_daemonize");

	for (;;) {
		if (config.flags & CONFIG_FL_PIDF_CREATE)
			_file_pid_create(config.pidf_name);

		/* Make sure that we receive a valid status value... otherwise jump out of here. */
		if ((status = _bexec(config.binary, config.args)) == -1) {
			log_warn("main(): _bexec(): Unable to execute binary '%s': %s.\n", config.binary, strerror(errno));
			break;
		}

		/* Log process termination */
		log_info("main(): _bexec(): Execution of '%s' terminated (Exit status: %d).\n", config.binary, WEXITSTATUS(status));

		/* Log any signals that caused the termination */
		if (WIFSIGNALED(status))
			log_info("main(): Child process \'%s\' was terminated due to unhandled signal %d.\n", config.binary, WTERMSIG(status));

		/* Check if the exit status refers to a bad runtime state */
		if (WEXITSTATUS(status) == PROCESS_EXIT_STATUS_CUSTOM_BAD_RUNTIME_OR_CONFIG) {
			log_info("main(): Child process \'%s\' won't be restarted due to runtime or configuration errors.\n", config.binary);

			/* If so, do not attempt to restart the process, even if explicitly requested
			 * by command line options.
			 */
			break;
		}

		if (config.flags & CONFIG_FL_PROC_RSTIGN) {
			log_info("main(): Restarting child \'%s\' regardless of exit status code.\n", config.binary);

			/* Restart child regardless of signals and exit codes */
			_main_loop_restart_prepare();

			continue;
		} else if ((config.flags & CONFIG_FL_PROC_RSTUSIG) && WIFSIGNALED(status) && (WTERMSIG(status) != SIGKILL) && (WTERMSIG(status) != SIGQUIT)) {
			log_info("main(): Restarting child \'%s\' since its termination was caused by an unhandled signal other than SIGKILL and SIGQUIT. (Termination signal was %d)\n", config.binary, WTERMSIG(status));

			/* Restart child if any unhandled signal other than KILL and QUIT caused its
			 * termination
			 */
			_main_loop_restart_prepare();

			continue;
		} else if ((config.flags & CONFIG_FL_PROC_RESTART) && WEXITSTATUS(status)) {
			log_info("main(): Restarting child \'%s\' due to a non-zero exit status code.", config.binary);

			/* Restart child is exit status code isn't zero */
			_main_loop_restart_prepare();

			continue;
		}

		break;
	}

	if (status < 0)
		_failure("_bexec");

	if (config.flags & CONFIG_FL_PIDF_CREATE) {
		if (unlink(config.pidf_name) < 0)
			_failure("unlink");
	}

	_config_destroy();

	_log_destroy();

	return 0;
}