static void sigstop(int signo)
{
	mw_stop_aaa();
	delete_pid_file(IMAGE_SERVER_PROC);
	APP_PRINTF("Exit image_server!\n");
	exit(1);
}
Exemple #2
0
static void
sigint (int foo)
{
    arla_warnx (ADEBMISC, "fatal signal received");
    store_state ();
    delete_pid_file ();
    exit (0);
}
Exemple #3
0
/** Ths signal handler for nasty, fatal signals.
 */
static void handle_fatal_signal(int sig, siginfo_t *siginfo, void *ctx)
{
	int i, POSSIBLY_UNUSED(res), bsize;
	void *bentries[128];
	char *buf = (char*)bentries;

	for (i = 0; i < NUM_FATAL_SIGNALS; ++i) {
		signal(FATAL_SIGNALS[i], SIG_IGN);
	}
	if (sig == SIGALRM) {
		snprintf(buf, sizeof(bentries), "%s ALARM EXPIRED\n",
			 (const char*)siginfo->si_value.sival_ptr);
		res = write(g_crash_log_fd, buf, strlen(buf));
	}
	snprintf(buf, sizeof(bentries), "HANDLE_FATAL_SIGNAL(sig=%d, "
			"name=%s)\n", sig, sys_siglist[sig]);
	res = write(g_crash_log_fd, buf, strlen(buf));
	signal_analyze_plat_data(ctx, buf, sizeof(bentries));
	res = write(g_crash_log_fd, buf, strlen(buf));

	bsize = backtrace(bentries, sizeof(bentries)/sizeof(bentries[0]));
	backtrace_symbols_fd(bentries, bsize, g_crash_log_fd);
	snprintf(buf, sizeof(bentries), "END_HANDLE_FATAL_SIGNAL\n");
	res = write(g_crash_log_fd, buf, strlen(buf));
	fsync(g_crash_log_fd);

	if (g_crash_log_fd != STDERR_FILENO) {
		/* This function reads the file we just wrote, and sends it to
		 * some other output streams.
		 *
		 * We always write it to stderr. Most of the time, stderr will
		 * be hooked to /dev/null, but sometimes it isn't.
		 *
		 * If use_syslog was specified, we write the file to syslog.
		 * Technically, we're not supposed to do this, because syslog is
		 * not a signal-safe function.  However, we've already written
		 * out the crash_log, so there will be some record of what went
		 * wrong, even if we crash and burn in this function.  Also, in
		 * practice, syslog tends to do non-signal-safe stuff like call
		 * malloc only on the first invocation or when openlog is
		 * called.
		 */
		regurgitate_fd((char*)bentries, sizeof(bentries),
				 g_crash_log_fd, -1, g_use_syslog);
	}
	/* If the pid file has not been set up, this will do nothing. */
	delete_pid_file();
	/* dump fast logs */
	fast_log_mgr_dump_all(g_fast_log_mgr, g_fast_log_fd);
	snprintf(buf, sizeof(bentries), "END_FAST_LOG_DUMP\n");
	res = write(g_crash_log_fd, buf, strlen(buf));
	fsync(g_crash_log_fd);
	/* Call the previously install signal handler.
	 * Probably, this will dump core. */
	g_prev_handlers[sig](sig, siginfo, ctx);
}
Exemple #4
0
/*
 * semaphore get/put wrapper
 */
int down(int sem_id)
{
	struct sembuf buf = {
		.sem_num = 0,
		.sem_op  = -1,
		.sem_flg = SEM_UNDO,
	};
        return semop(sem_id, &buf, 1);
}

int up(int sem_id)
{
	struct sembuf buf = {
		.sem_num = 0,
		.sem_op  = 1,
		.sem_flg = SEM_UNDO,
	};
        return semop(sem_id, &buf, 1);
}

void delete_pid_file(void)
{
	if (!pid_filename)
		return;

	if (unlink(pid_filename) < 0)
		perror(pid_filename);
}

void update_pid_file(pid_t pid)
{
	FILE *file;

	if (!pid_filename)
		return;

	file = fopen(pid_filename, "w");
	if (!file) {
		perror(pid_filename);
		exit(1);
	}

	fprintf(file, "%d\n", pid);
	fclose(file);
}


void sighandler(int sig, siginfo_t *si, void *arg)
{
	up(sem_id);
	delete_pid_file();

	fprintf(stderr, "Fatal signal %d\n", sig);
	exit(1);
}
void application::stop()
{
    LOG_COMP_INFO(application, "terminating");

    try
    {
        server_.stop();
        delete_pid_file();
    }
    catch(std::exception const& e)
    {
        LOG_COMP_FAILURE(application, e);
    }
}
Exemple #6
0
/* Cleanup and then exit */
void terminate_dird(int sig)
{
   static bool already_here = false;

   if (already_here) {                /* avoid recursive temination problems */
      bmicrosleep(2, 0);              /* yield */
      exit(1);
   }
   already_here = true;
   debug_level = 0;                   /* turn off debug */
   stop_watchdog();
   db_sql_pool_destroy();
   db_flush_backends();
   unload_dir_plugins();
   write_state_file(me->working_directory, "bareos-dir", get_first_port_host_order(me->DIRaddrs));
   delete_pid_file(me->pid_directory, "bareos-dir", get_first_port_host_order(me->DIRaddrs));
   term_scheduler();
   term_job_server();
   if (runjob) {
      free(runjob);
   }
   if (configfile != NULL) {
      free(configfile);
   }
   if (debug_level > 5) {
      print_memory_pool_stats();
   }
   if (my_config) {
      my_config->free_resources();
      free(my_config);
      my_config = NULL;
   }
   stop_UA_server();
   term_msg();                        /* terminate message handler */
   cleanup_crypto();
   close_memory_pool();               /* release free memory in pool */
   lmgr_cleanup_main();
   sm_dump(false);
   exit(sig);
}
int main(int argc, char *argv[])
{
	pid_t pid;
	/* Reset signal handlers */
	if (daemon_reset_sigs(-1) < 0) {
		daemon_log(LOG_ERR, "Failed to reset all signal handlers: %s",
			strerror(errno));
		return 1;
	}
	/* Unblock signals */
	if (daemon_unblock_sigs(-1) < 0) {
		daemon_log(LOG_ERR, "Failed to unblock all signals: %s",
			strerror(errno));
	}
	/* Set indetification string for the daemon for both syslog and PID file */
	daemon_log_ident = daemon_ident_from_argv0(argv[0]);
	daemon_pid_file_ident = daemon_log_ident;
	//(LOG_ERR, "The log ident is %s\n",daemon_log_ident);
	daemon_pid_file_proc = get_pid_file_proc;
	sprintf (image_pid_file, "/var/run/%s.pid", daemon_pid_file_ident);
	/* Check if we are called with -k parameter */
	if (argc >= 2 && !strcmp(argv[1], "-k")) {
		int ret;
		/* Kill daemon with SIGTERM */
		/* Check if the new function daemon_pid_file_kill_wait() is available,
			if it is, use it. */
		if ((ret = daemon_pid_file_kill_wait(SIGTERM, 5)) < 0)
			daemon_log(LOG_WARNING, "Failed to kill daemon: %s",
				strerror(errno));
		return ret < 0 ? 1 : 0;
	}
	/* Check that the daemon is not rung twice a the same time */
	if ((pid = daemon_pid_file_is_running()) >= 0) {
		daemon_log(LOG_ERR, "Daemon already running on PID file %u", pid);
		return 1;
	}
	/* Prepare for return value passing from the initialization procedure
		of the daemon process */
	if (daemon_retval_init() < 0) {
		daemon_log(LOG_ERR, "Failed to create pipe.");
		return 1;
	}
	/* Do the fork */
	if ((pid = daemon_fork()) < 0) {
		/* Exit on error */
		daemon_retval_done();
		return 1;
	} else if (pid) {  /* The parent */
		int ret;
		/* Wait for 20 seconds for the return value passed from the daemon
			process */
		if ((ret = daemon_retval_wait(20)) < 0) {
			daemon_log(LOG_ERR, "Count not receive return value from daemon"
				"process: %s", strerror(errno));
		}
		//daemon_log(ret != 0 ? LOG_ERR : LOG_INFO,
		//	"Daemon returned %i as return value.", ret);
		return ret;
	} else {  /* The daemon */
		int fd, quit = 0;
		fd_set fds;
		pthread_t sock_thread;
		pthread_t nl_thread;
		/* Close FDs */
		if (daemon_close_all(-1) < 0) {
			daemon_log(LOG_ERR, "Failed to close all file descriptors: %s",
				strerror(errno));
			/* Send the error condition to the parent process */
			daemon_retval_send(1);
			goto finish;
		}
		/* Create the PID file */
		if (daemon_pid_file_create() < 0) {
			daemon_log(LOG_ERR, "Could not create PID file (%s).",
				strerror(errno));
			daemon_retval_send(2);
			goto finish;
		}
		/* Initialize signal handling */
		if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, 0) < 0) {
			daemon_log(LOG_ERR, "Could not register signal handlers (%s).",
				strerror(errno));
			daemon_retval_send(3);
			goto finish;
		}
		/* Init task */
		init_image_config(argc, argv);
		init_netlink();
		/* Send OK to parent process */
		daemon_retval_send(0);
		daemon_log(LOG_INFO, "Sucessfully started");
		/* Main task*/
		pthread_create(&nl_thread, NULL, (void *)netlink_loop, (void *)NULL);
		#if 0
		pthread_create(&sock_thread, NULL, (void *)socket_loop, (void *)NULL);
		#endif
		pthread_create(&sock_thread, NULL, (void *)mq_loop, (void *)NULL);
		/* Prepare for select() on the signal fd */
		FD_ZERO(&fds);
		fd = daemon_signal_fd();
		FD_SET(fd, &fds);
		while (!quit) {
			fd_set fds2 = fds;
			/* Wait for an incoming signal */
			if (select(FD_SETSIZE, &fds2, 0, 0, 0) < 0) {
				/* If we've been interrupted by an incoming signal, continue */
				if (errno == EINTR)
					continue;
				daemon_log(LOG_ERR, "select(): %s", strerror(errno));
				break;
			}
			/* Check if a signal has been recieved */
			if (FD_ISSET(fd, &fds2)) {
				int sig;
				/* Get signal */
				if ((sig = daemon_signal_next()) <= 0) {
					daemon_log(LOG_ERR, "daemon_signal_next() failed: %s",
						strerror(errno));
					break;
				}
				/* Dispatch signal */
				switch (sig) {
					case SIGINT:
					case SIGQUIT:
					case SIGTERM:
						daemon_log(LOG_WARNING, "Got SIGINT, SIGQUIT or"
							"SIGTERM.");
						if (nl_image_config.nl_connected == 1) {
							nl_image_config.nl_connected = 0;
							if (nl_send_image_session_cmd(
								IMAGE_SESSION_CMD_DISCONNECT) < 0) {
								printf("Failed to remove connection with"
									"kernel!\n");
							}
						}
						quit = 1;
						break;
					case SIGHUP:
						daemon_log(LOG_INFO, "Got a HUP");
						daemon_exec("/", NULL, "/bin/ls", "ls", (char*) NULL);
						break;
				}
			}
		}
		/* Do a cleanup */
finish:
		delete_pid_file(IMAGE_SERVER_PROC);
		daemon_log(LOG_INFO, "Exiting...");
		daemon_retval_send(255);
		daemon_signal_done();
		daemon_pid_file_remove();
		return 0;
	}
}
int main(int argc, const char* argv[])
{
  FILE *log = get_log (NULL);

  switch (process_options(argc, argv, log))
    {
      case 0:
        break;
      case -1:
        exit(EXIT_SUCCESS);
      default:
        exit(EXIT_FAILURE);
    }

  if ( ! arg_nodaemonize )
    {
      close_log (log); /* close before daemonizing */
      daemonize();
    }

  log = get_log (log); /* reopen */
  LOG_INF(log, "Initializing - lwes-journaller-%s\n", VERSION);

  if (write_pid_file() != 0)
    {
      LOG_ER(log,"Can't open PID file \"%s\"\n", arg_pid_file);
    }

  if ( arg_njournalls > 30 )
    {
      LOG_WARN(log, "suspiciously large (%d) number of journals.",
               arg_njournalls);
    }

  LOG_INF(log, "Starting up - lwes-journaller-%s using %s model\n",
          VERSION, arg_proc_type);

  if ( strcmp(arg_proc_type, ARG_PROCESS) == 0 )
    {
      process_model(argv, log);
    }

  if ( strcmp(arg_proc_type, ARG_THREAD) == 0 )
    {
      thread_model(log);
    }

  if ( strcmp(arg_proc_type, ARG_SERIAL) == 0 )
    {
      serial_model(log);
    }

  int r = 0;
  if ((r = delete_pid_file()) < 0)
    {
      LOG_ER(log,"Unable to delete pid file : %s\n",
             delete_pid_file, strerror(r));
    }
  options_destructor();

  LOG_INF(log, "Normal shutdown complete - lwes-journaller-%s\n", VERSION);

  close_log (log);

  return 0;
}
Exemple #9
0
static void
sighup (int foo)
{
    store_state ();
    delete_pid_file ();
}
Exemple #10
0
int main(int argc, char *argv[])
{
	char *conf_filename;
	int result;
	int sock;
	int wait_count;
	pthread_t schedule_tid;
	struct sigaction act;
	ScheduleEntry scheduleEntries[SCHEDULE_ENTRIES_MAX_COUNT];
	ScheduleArray scheduleArray;
	char pidFilename[MAX_PATH_SIZE];
	bool stop;

	if (argc < 2)
	{
		usage(argv[0]);
		return 1;
	}

	g_current_time = time(NULL);
	g_up_time = g_current_time;

	log_init2();
	trunk_shared_init();

	conf_filename = argv[1];
	if ((result=get_base_path_from_conf_file(conf_filename,
		g_fdfs_base_path, sizeof(g_fdfs_base_path))) != 0)
	{
		log_destroy();
		return result;
	}

	snprintf(pidFilename, sizeof(pidFilename),
		"%s/data/fdfs_storaged.pid", g_fdfs_base_path);
	if ((result=process_action(pidFilename, argv[2], &stop)) != 0)
	{
		if (result == EINVAL)
		{
			usage(argv[0]);
		}
		log_destroy();
		return result;
	}
	if (stop)
	{
		log_destroy();
		return 0;
	}

#if defined(DEBUG_FLAG) && defined(OS_LINUX)
	if (getExeAbsoluteFilename(argv[0], g_exe_name, \
		sizeof(g_exe_name)) == NULL)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return errno != 0 ? errno : ENOENT;
	}
#endif

	memset(g_bind_addr, 0, sizeof(g_bind_addr));
	if ((result=storage_func_init(conf_filename, \
			g_bind_addr, sizeof(g_bind_addr))) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}

	sock = socketServer(g_bind_addr, g_server_port, &result);
	if (sock < 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}

	if ((result=tcpsetserveropt(sock, g_fdfs_network_timeout)) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}

	daemon_init(false);
	umask(0);
	if ((result=write_to_pid_file(pidFilename)) != 0)
	{
		log_destroy();
		return result;
	}

	if ((result=storage_sync_init()) != 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"storage_sync_init fail, program exit!", __LINE__);
		g_continue_flag = false;
		return result;
	}

	if ((result=tracker_report_init()) != 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"tracker_report_init fail, program exit!", __LINE__);
		g_continue_flag = false;
		return result;
	}

	if ((result=storage_service_init()) != 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"storage_service_init fail, program exit!", __LINE__);
		g_continue_flag = false;
		return result;
	}

	if ((result=set_rand_seed()) != 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"set_rand_seed fail, program exit!", __LINE__);
		g_continue_flag = false;
		return result;
	}

	memset(&act, 0, sizeof(act));
	sigemptyset(&act.sa_mask);

	act.sa_handler = sigUsrHandler;
	if(sigaction(SIGUSR1, &act, NULL) < 0 || \
		sigaction(SIGUSR2, &act, NULL) < 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"call sigaction fail, errno: %d, error info: %s", \
			__LINE__, errno, STRERROR(errno));
		logCrit("exit abnormally!\n");
		return errno;
	}

	act.sa_handler = sigHupHandler;
	if(sigaction(SIGHUP, &act, NULL) < 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"call sigaction fail, errno: %d, error info: %s", \
			__LINE__, errno, STRERROR(errno));
		logCrit("exit abnormally!\n");
		return errno;
	}
	
	act.sa_handler = SIG_IGN;
	if(sigaction(SIGPIPE, &act, NULL) < 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"call sigaction fail, errno: %d, error info: %s", \
			__LINE__, errno, STRERROR(errno));
		logCrit("exit abnormally!\n");
		return errno;
	}

	act.sa_handler = sigQuitHandler;
	if(sigaction(SIGINT, &act, NULL) < 0 || \
		sigaction(SIGTERM, &act, NULL) < 0 || \
		sigaction(SIGQUIT, &act, NULL) < 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"call sigaction fail, errno: %d, error info: %s", \
			__LINE__, errno, STRERROR(errno));
		logCrit("exit abnormally!\n");
		return errno;
	}

#if defined(DEBUG_FLAG)

/*
#if defined(OS_LINUX)
	memset(&act, 0, sizeof(act));
        act.sa_sigaction = sigSegvHandler;
        act.sa_flags = SA_SIGINFO;
        if (sigaction(SIGSEGV, &act, NULL) < 0 || \
        	sigaction(SIGABRT, &act, NULL) < 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"call sigaction fail, errno: %d, error info: %s", \
			__LINE__, errno, STRERROR(errno));
		logCrit("exit abnormally!\n");
		return errno;
	}
#endif
*/

	memset(&act, 0, sizeof(act));
	sigemptyset(&act.sa_mask);
	act.sa_handler = sigDumpHandler;
	if(sigaction(SIGUSR1, &act, NULL) < 0 || \
		sigaction(SIGUSR2, &act, NULL) < 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"call sigaction fail, errno: %d, error info: %s", \
			__LINE__, errno, STRERROR(errno));
		logCrit("exit abnormally!\n");
		return errno;
	}
#endif

#ifdef WITH_HTTPD
	if (!g_http_params.disabled)
	{
		if ((result=storage_httpd_start(g_bind_addr)) != 0)
		{
			logCrit("file: "__FILE__", line: %d, " \
				"storage_httpd_start fail, " \
				"program exit!", __LINE__);
			return result;
		}
	}
#endif

	if ((result=tracker_report_thread_start()) != 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"tracker_report_thread_start fail, " \
			"program exit!", __LINE__);
		g_continue_flag = false;
		storage_func_destroy();
		log_destroy();
		return result;
	}

	scheduleArray.entries = scheduleEntries;

	memset(scheduleEntries, 0, sizeof(scheduleEntries));
	scheduleEntries[0].id = 1;
	scheduleEntries[0].time_base.hour = TIME_NONE;
	scheduleEntries[0].time_base.minute = TIME_NONE;
	scheduleEntries[0].interval = g_sync_log_buff_interval;
	scheduleEntries[0].task_func = log_sync_func;
	scheduleEntries[0].func_args = &g_log_context;

	scheduleEntries[1].id = 2;
	scheduleEntries[1].time_base.hour = TIME_NONE;
	scheduleEntries[1].time_base.minute = TIME_NONE;
	scheduleEntries[1].interval = g_sync_binlog_buff_interval;
	scheduleEntries[1].task_func = fdfs_binlog_sync_func;
	scheduleEntries[1].func_args = NULL;

	scheduleEntries[2].id = 3;
	scheduleEntries[2].time_base.hour = TIME_NONE;
	scheduleEntries[2].time_base.minute = TIME_NONE;
	scheduleEntries[2].interval = g_sync_stat_file_interval;
	scheduleEntries[2].task_func = fdfs_stat_file_sync_func;
	scheduleEntries[2].func_args = NULL;

	scheduleArray.count = 3;
	if (g_if_use_trunk_file)
	{
		scheduleEntries[scheduleArray.count].id = 4;
		scheduleEntries[scheduleArray.count].time_base.hour = TIME_NONE;
		scheduleEntries[scheduleArray.count].time_base.minute=TIME_NONE;
		scheduleEntries[scheduleArray.count].interval = 1;
		scheduleEntries[scheduleArray.count].task_func = \
					trunk_binlog_sync_func;
		scheduleEntries[scheduleArray.count].func_args = NULL;
		scheduleArray.count++;
	}

	if (g_use_access_log)
	{
		scheduleEntries[scheduleArray.count].id = 5;
		scheduleEntries[scheduleArray.count].time_base.hour = TIME_NONE;
		scheduleEntries[scheduleArray.count].time_base.minute=TIME_NONE;
		scheduleEntries[scheduleArray.count].interval = \
					g_sync_log_buff_interval;
		scheduleEntries[scheduleArray.count].task_func = log_sync_func;
		scheduleEntries[scheduleArray.count].func_args = \
					&g_access_log_context;
		scheduleArray.count++;

		if (g_rotate_access_log)
		{
			scheduleEntries[scheduleArray.count].id = 6;
			scheduleEntries[scheduleArray.count].time_base = \
					g_access_log_rotate_time;
			scheduleEntries[scheduleArray.count].interval = \
					24 * 3600;
			scheduleEntries[scheduleArray.count].task_func = \
					log_notify_rotate;
			scheduleEntries[scheduleArray.count].func_args = \
					&g_access_log_context;
			scheduleArray.count++;
		}
	}

	if (g_rotate_error_log)
	{
		scheduleEntries[scheduleArray.count].id = 7;
		scheduleEntries[scheduleArray.count].time_base = \
				g_error_log_rotate_time;
		scheduleEntries[scheduleArray.count].interval = \
				24 * 3600;
		scheduleEntries[scheduleArray.count].task_func = \
				log_notify_rotate;
		scheduleEntries[scheduleArray.count].func_args = \
				&g_log_context;
		scheduleArray.count++;
	}

	if ((result=sched_start(&scheduleArray, &schedule_tid, \
		g_thread_stack_size, (bool * volatile)&g_continue_flag)) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}

	if ((result=set_run_by(g_run_by_group, g_run_by_user)) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}

	if ((result=storage_dio_init()) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}
	log_set_cache(true);

	bTerminateFlag = false;
	bAcceptEndFlag = false;
	
	storage_accept_loop(sock);
	bAcceptEndFlag = true;

	fdfs_binlog_sync_func(NULL);  //binlog fsync

	if (g_schedule_flag)
	{
		pthread_kill(schedule_tid, SIGINT);
	}

	storage_terminate_threads();
	storage_dio_terminate();

	kill_tracker_report_threads();
	kill_storage_sync_threads();

	wait_count = 0;
	while (g_storage_thread_count != 0 || \
		g_dio_thread_count != 0 || \
		g_tracker_reporter_count > 0 || \
		g_schedule_flag)
	{
/*
#if defined(DEBUG_FLAG) && defined(OS_LINUX)
		if (bSegmentFault)
		{
			sleep(5);
			break;
		}
#endif
*/

		usleep(10000);
		if (++wait_count > 6000)
		{
			logWarning("waiting timeout, exit!");
			break;
		}
	}

	tracker_report_destroy();
	storage_service_destroy();
	storage_sync_destroy();
	storage_func_destroy();

	if (g_if_use_trunk_file)
	{
		trunk_sync_destroy();
		storage_trunk_destroy();
	}

	logInfo("exit normally.\n");
	log_destroy();
	
	delete_pid_file(pidFilename);
	return 0;
}
Exemple #11
0
int main(int argc, char *argv[])
{
	char *conf_filename;
	int result;
	int wait_count;
	int sock;
	pthread_t schedule_tid;
	struct sigaction act;
	ScheduleEntry scheduleEntries[SCHEDULE_ENTRIES_COUNT];
	ScheduleArray scheduleArray;
	char pidFilename[MAX_PATH_SIZE];
	bool stop;

	if (argc < 2)
	{
		usage(argv[0]);
		return 1;
	}

	g_current_time = time(NULL);
	g_up_time = g_current_time;
	srand(g_up_time);

	log_init2();
	//通过指定的conf文件,获取base path
	conf_filename = argv[1];
	if ((result=get_base_path_from_conf_file(conf_filename,
		g_fdfs_base_path, sizeof(g_fdfs_base_path))) != 0)
	{
		log_destroy();
		return result;
	}
	//启动程序,或者通过文件中的pid来kill掉之前的进程
	snprintf(pidFilename, sizeof(pidFilename),
		"%s/data/fdfs_trackerd.pid", g_fdfs_base_path);
	if ((result=process_action(pidFilename, argv[2], &stop)) != 0)
	{
		if (result == EINVAL)
		{
			usage(argv[0]);
		}
		log_destroy();
		return result;
	}
	if (stop)
	{
		log_destroy();
		return 0;
	}

#if defined(DEBUG_FLAG) && defined(OS_LINUX)
	if (getExeAbsoluteFilename(argv[0], g_exe_name, \
		sizeof(g_exe_name)) == NULL)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return errno != 0 ? errno : ENOENT;
	}
#endif

	memset(bind_addr, 0, sizeof(bind_addr));
	if ((result=tracker_load_from_conf_file(conf_filename, \
			bind_addr, sizeof(bind_addr))) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}
	//g_tracker_last_status只记录了uptime和last check time作用未知
	if ((result=tracker_load_status_from_file(&g_tracker_last_status)) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}

	base64_init_ex(&g_base64_context, 0, '-', '_', '.');
	if ((result=set_rand_seed()) != 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"set_rand_seed fail, program exit!", __LINE__);
		return result;
	}
	//内存分配及历史group和storage载入
	if ((result=tracker_mem_init()) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}

	sock = socketServer(bind_addr, g_server_port, &result);
	if (sock < 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}

	if ((result=tcpsetserveropt(sock, g_fdfs_network_timeout)) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}
	//后台运行
	daemon_init(false);
	umask(0);
	//将pid记录到文件中
	if ((result=write_to_pid_file(pidFilename)) != 0)
	{
		log_destroy();
		return result;
	}
	//启动工作线程,这一块需要重点看
	if ((result=tracker_service_init()) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}
	//注册信号处理函数
	memset(&act, 0, sizeof(act));
	sigemptyset(&act.sa_mask);

	act.sa_handler = sigUsrHandler;
	if(sigaction(SIGUSR1, &act, NULL) < 0 || \
		sigaction(SIGUSR2, &act, NULL) < 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"call sigaction fail, errno: %d, error info: %s", \
			__LINE__, errno, STRERROR(errno));
		logCrit("exit abnormally!\n");
		return errno;
	}

	act.sa_handler = sigHupHandler;
	if(sigaction(SIGHUP, &act, NULL) < 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"call sigaction fail, errno: %d, error info: %s", \
			__LINE__, errno, STRERROR(errno));
		logCrit("exit abnormally!\n");
		return errno;
	}
	
	act.sa_handler = SIG_IGN;
	if(sigaction(SIGPIPE, &act, NULL) < 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"call sigaction fail, errno: %d, error info: %s", \
			__LINE__, errno, STRERROR(errno));
		logCrit("exit abnormally!\n");
		return errno;
	}

	act.sa_handler = sigQuitHandler;
	if(sigaction(SIGINT, &act, NULL) < 0 || \
		sigaction(SIGTERM, &act, NULL) < 0 || \
		sigaction(SIGQUIT, &act, NULL) < 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"call sigaction fail, errno: %d, error info: %s", \
			__LINE__, errno, STRERROR(errno));
		logCrit("exit abnormally!\n");
		return errno;
	}

#if defined(DEBUG_FLAG)
/*
#if defined(OS_LINUX)
	memset(&act, 0, sizeof(act));
	sigemptyset(&act.sa_mask);
        act.sa_sigaction = sigSegvHandler;
        act.sa_flags = SA_SIGINFO;
        if (sigaction(SIGSEGV, &act, NULL) < 0 || \
        	sigaction(SIGABRT, &act, NULL) < 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"call sigaction fail, errno: %d, error info: %s", \
			__LINE__, errno, STRERROR(errno));
		logCrit("exit abnormally!\n");
		return errno;
	}
#endif
*/

	memset(&act, 0, sizeof(act));
	sigemptyset(&act.sa_mask);
	act.sa_handler = sigDumpHandler;
	if(sigaction(SIGUSR1, &act, NULL) < 0 || \
		sigaction(SIGUSR2, &act, NULL) < 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"call sigaction fail, errno: %d, error info: %s", \
			__LINE__, errno, STRERROR(errno));
		logCrit("exit abnormally!\n");
		return errno;
	}
#endif

#ifdef WITH_HTTPD
	if (!g_http_params.disabled)
	{
		if ((result=tracker_httpd_start(bind_addr)) != 0)
		{
			logCrit("file: "__FILE__", line: %d, " \
				"tracker_httpd_start fail, program exit!", \
				__LINE__);
			return result;
		}

	}

	if ((result=tracker_http_check_start()) != 0)
	{
		logCrit("file: "__FILE__", line: %d, " \
			"tracker_http_check_start fail, " \
			"program exit!", __LINE__);
		return result;
	}
#endif

	if ((result=set_run_by(g_run_by_group, g_run_by_user)) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}
	//schedule 调度线程,主要作用待细看
	scheduleArray.entries = scheduleEntries;
	scheduleArray.count = 0;
	memset(scheduleEntries, 0, sizeof(scheduleEntries));
	//日志处理,日志是先存在cache中的,需要定时存储
	INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count],
		scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE,
		g_sync_log_buff_interval, log_sync_func, &g_log_context);
	scheduleArray.count++;
	//用户检测trunk server服务器是否可用(trunk server是选定的一个storage)
	INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count],
		scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE,
		g_check_active_interval, tracker_mem_check_alive, NULL);
	scheduleArray.count++;
	//每5分钟刷新一下status
	INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count],
		scheduleArray.count + 1, 0, 0, 0,
		TRACKER_SYNC_STATUS_FILE_INTERVAL,
		tracker_write_status_to_file, NULL);
	scheduleArray.count++;

	if (g_rotate_error_log)
	{
		INIT_SCHEDULE_ENTRY_EX(scheduleEntries[scheduleArray.count],
			scheduleArray.count + 1, g_error_log_rotate_time,
			24 * 3600, log_notify_rotate, &g_log_context);
		scheduleArray.count++;

		if (g_log_file_keep_days > 0)
		{
			log_set_keep_days(&g_log_context, g_log_file_keep_days);

			INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count],
				scheduleArray.count + 1, 1, 0, 0, 24 * 3600,
				log_delete_old_files, &g_log_context);
			scheduleArray.count++;
		}
	}

	if ((result=sched_start(&scheduleArray, &schedule_tid, \
		g_thread_stack_size, (bool * volatile)&g_continue_flag)) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}
	//选主机制,tracker默认不会把自己加入队列
	if ((result=tracker_relationship_init()) != 0)
	{
		logCrit("exit abnormally!\n");
		log_destroy();
		return result;
	}

	log_set_cache(true);

	bTerminateFlag = false;
	bAcceptEndFlag = false;
	//accept线程,工作线程和消息接收线程是分开的
	tracker_accept_loop(sock);
	bAcceptEndFlag = true;
	if (g_schedule_flag)
	{
		pthread_kill(schedule_tid, SIGINT);
	}
	tracker_terminate_threads();

#ifdef WITH_HTTPD
	if (g_http_check_flag)
	{
		tracker_http_check_stop();
	}

	while (g_http_check_flag)
	{
		usleep(50000);
	}
#endif

	wait_count = 0;
	//线程数和调度flag还在,则继续运行程序
	while ((g_tracker_thread_count != 0) || g_schedule_flag)
	{

/*
#if defined(DEBUG_FLAG) && defined(OS_LINUX)
		if (bSegmentFault)
		{
			sleep(5);
			break;
		}
#endif
*/

		usleep(10000);
		if (++wait_count > 3000)
		{
			logWarning("waiting timeout, exit!");
			break;
		}
	}
	
	tracker_mem_destroy();
	tracker_service_destroy();
	tracker_relationship_destroy();
	
	logInfo("exit normally.\n");
	log_destroy();
	
	delete_pid_file(pidFilename);
	return 0;
}