Exemplo n.º 1
0
/**
* Cleanup all ipc resources
*/
static void ipc_shutdown(void)
{

	/* We need to block all signals to avoid race condition */
	sigset_t blocked_signals;
	(void) sigfillset(&blocked_signals);
	(void) sigprocmask(SIG_BLOCK, &blocked_signals, NULL);
	
	/* cleanup has already been done */
	if(cleanup == 1) {
		return;
	}
	cleanup = 1;

	/* If cnd has already been aquired, try to remove it (would return -1 if cnd had already been removed by other process) */
	if(cnd != -1) {
		(void) msemrm(cnd);
	}

	/* detach SHM Segment (So it can be free'd later, or by other process) */
	shm_detach();

	if(mtx != -1) {

		/* This fails with -1 if onother process has already done the cleanup of smh segment */
		if(semdown(mtx) != -1) {

			/*
			 * It might happen, that we only fail to aquire shm segment, but have a working mtx.
			 * In this case we will not destroy the mtx, because other processes might have created an shm segment and will therefor need a working mtx to free it.
			 */
			if(shm != -1) {

				(void) shmctl(shm, IPC_RMID, NULL);
				(void) semrm(mtx);

			} else {
				(void) semup(mtx);
			}

		}

	}

}
Exemplo n.º 2
0
/**
Uninitializes this process.

@param last Whether shared resources should also be uninitialized.
@return 0 if successful and -1 otherwise.
**/
int uninit(const bool last) {
	int result = 0;

	/*
	Unitializes the shared memory segment.
	*/
	if (shm_detach() == -1) {
		result = -1;
	}
	if (last) {
		if (shm_uninit() == -1) {
			result = -1;
		}

		/*
		Unitializes the display.
		*/
		if (curs_set(1) == ERR
				|| orig_wrefresh(stdscr) == ERR//TODO remove
				|| nocbreak() == ERR
				|| echo() == ERR
				|| orig_endwin() == ERR)
		{
			probno = log_error(UNINIT_PROBLEM);
			result = -1;
		}
	}

	/*
	Unitializes the functions.
	*/
	if (lib_uninit() == -1) {
		result = -1;
	}

	/*
	Unitializes the configuration.
	*/
	if (cfg_uninit() == -1) {
		result = -1;
	}

	return result;
}
Exemplo n.º 3
0
static void shm_close(void *addr)
{
	shm_detach(addr);
	shm_rm();
}
Exemplo n.º 4
0
/*** Detach from a shared memory area ***/
void _0x94_shm_detach(void) {
	shm_detach(current_process);
	
	current_process->state = READY;
}
Exemplo n.º 5
0
/**
* Main entry point
*
* @param argc argument counter
* @param argv argument array
*
* @return EXIT_SUCCESS on success, EXIT_FAILURE otherwise
*/
int main(int argc, char  **argv)
{

	struct sigaction s;
	/* We only catch INT and QUIT (allthough we could catch TERM as well) */
	const int signals[] = { SIGINT, SIGQUIT };

	parse_args(argc, argv);

	s.sa_handler = signal_handler;
	s.sa_flags = SA_RESTART;

	/* Block all signals here ... */
	if(sigfillset(&s.sa_mask) < 0) {
		bail_out(EXIT_FAILURE, "Error creating Signal Block Mask");
	}

	/* ... unblock signals and set handler  */
	for(int i = 0; i < 2; ++i) {

		if(sigaction(signals[i], &s, NULL) < 0) {
			bail_out(EXIT_FAILURE, "Failed to sigaction for signale %d", signals[i]);
		}

	}
	
	/* Init ipc variables */
	ipc_init();

#ifdef _BUILD_READIN

	{
		/* readin reads stdin line wise (max MAX_BUF_SIZE - 1 chars) */
		char buf[MAX_BUF_SIZE];
		while(fgets(buf, MAX_BUF_SIZE, stdin) != NULL) {

			/* ... and writes them to shm */
			if(ipc_write(buf) == -1) { /* Write has failed, propably ipc channels have been removed by other process */
				bail_out(EXIT_FAILURE, "Error writing to shared memory");
			}

		}

		if(ipc_write(NULL) == -1) { /* This signals waiting read processed an EOF */
			bail_out(EXIT_FAILURE, "Error writing to shared memory");
		}

		shm_detach(); /* Normal shutdown for readin */

	}
	

#else
	{

		int c = 0;
		
		/* chstat keeps on listening */
		while(1) {

			/* wait for read queue to open up, generate statistic */
			c = ipc_process();

			if(c == -1) { /* Error reading from shmem, probably ipc channels have been removed by other process */
				bail_out(EXIT_FAILURE, "Error reading from shared memory");
			} else if(c == 0) { /* EOF */
				print_stat();
				break;
			} else if(opt_v == 1) { /* If called with -v */
				print_stat();
			}

		}

		ipc_shutdown();	/* Normal shutdown for chstat */
	}

#endif	

	return 0;

}
Exemplo n.º 6
0
/**
	Carries out simulation setup and management.
	@param argc The number of arguments
	@param argv The array of arguments
*/
int main(int argc, char *argv[]) {
	int *results, *shm_states;
	int i, op_count, proc_id;
	char *tmp_operator, *cmd;
	list *commands;
	operation *shm_operations;
	
	if(signal(SIGTERM, &stop_execution) == SIG_ERR) {
		write_to_fd(2, "Failed to register signal\n");
		exit(1);
	}
	if(argc != 3) {
		write_to_fd(2, "Usage: main.x <source file> <results file>\n");
		exit(1);
	}
	commands = parse_file(argv[1]);
	processors = atoi(list_extract(commands));
	if (processors <= 0) {
		write_to_fd(2, "Invalid number of processors\n");
		exit(1);
	}
	write_with_int(1, "Number of processors: ", processors);
	op_count = list_count(commands);
	if (op_count == 0) {
		write_to_fd(2, "No operations provided\n");
		exit(1);
	}
	write_with_int(1, "Number of operations: ", op_count);		
	results = (int *) malloc(op_count * sizeof(int));
	if (results == NULL) {
		write_to_fd(2, "Failed to allocate results array\n");
		exit(1);	
	}
	
	init_ipc(2 * processors + 2, processors * sizeof(operation), processors * sizeof(int), 0666 | IPC_CREAT | IPC_EXCL);
	write_with_int(1, "Created semaphore set with ID ", ipc_id[0]);
	write_with_int(1, "Created shm for operations with ID ", ipc_id[1]);
	write_with_int(1, "Created shm for states with ID ", ipc_id[2]);
	init_sems(processors);
	shm_operations = (operation *) shm_attach(ipc_id[1]);
	shm_states = (int *) shm_attach(ipc_id[2]);
	
	for (i = 0; i < processors; ++i)
		shm_states[i] = 0;
	
	start_processors();
	for (i = 1; list_count(commands) > 0; ++i) {
		cmd = list_extract(commands);
		write_with_int(1, "\nOperation #", i);
		proc_id = atoi(strtok(cmd, " "));
		sem_p(2 * processors + 1);
		if (proc_id-- == 0) {
			proc_id = find_proc(shm_states);
		}
		write_with_int(1, "Waiting for processor ", proc_id + 1);
		sem_p(2 * proc_id);
		write_with_int(1, "Delivering operation to processor ", proc_id + 1);
		if (shm_states[proc_id] != 0) {
			results[(shm_states[proc_id] + 1) * -1] = shm_operations[proc_id].num1;
			write_with_int(1, "Previous result: ", shm_operations[proc_id].num1);
		}
		shm_operations[proc_id].num1 = atoi(strtok(NULL, " "));
		tmp_operator = strtok(NULL, " ");
		shm_operations[proc_id].op = *tmp_operator;
		shm_operations[proc_id].num2 = atoi(strtok(NULL, " "));
		shm_states[proc_id] = i;
		write_with_int(1, "Operation delivered. Unblocking processor ", proc_id + 1);
		sem_v((2 * proc_id) + 1);
		free(cmd);
	}
	
	list_destruct(commands);
	
	for (i = 0; i < processors; ++i) {
		sem_p(2 * i);
		write_with_int(1, "\nPassing termination command to processor #", i + 1);
		if (shm_states[i] != 0) {
			results[(shm_states[i] + 1) * -1] = shm_operations[i].num1;
			write_with_int(1, "Last result: ", shm_operations[i].num1);
		}
		shm_operations[i].op = 'K';
		sem_v((2 * i) + 1);
	}

	for (i = 0; i < processors; ++i) 
		if(wait(NULL) == -1)
			write_to_fd(2, "Wait failed\n");
			
	write_to_fd(1, "\nAll processors exited. Writing output file\n");
	write_results(argv[2], results, op_count);
	free(results);
	write_to_fd(1, "Closing IPCs\n");
	shm_detach((void *) shm_operations);
	shm_detach((void *) shm_states);
	close_ipc();
	exit(0);
}
Exemplo n.º 7
0
int main (int argc, char *argv[]){

        slave_context context;
        char *str = (char *) malloc(sizeof(char) * 128);

        //-----------------------------------------------
        // RECUPERO LE INFORMAZIONI DEL PROCESSO
        //-----------------------------------------------
        slave_context_init(&context, argv);

        //-----------------------------------------------
        //      CICLO PER SVOLGERE IL COMANDO
        //-----------------------------------------------
        while(1){

                //-----------------------------------------------
                //      INCREMENTO I PROCESSI LIBERI
                //-----------------------------------------------
                sem_signal(SEMPROCFREE, context.sync_id.semid_sys  );

                //-----------------------------------------------
                //      SEGNALO DI AVER FINITO IL LAVORO PRECEDENTE
                //-----------------------------------------------
                sem_signal(context.id + 1,context.sync_id.semid_finish  );

                //-----------------------------------------------
                //      ASPETTO DI RICEVERE IL SEGNALE START
                //-----------------------------------------------
                sem_wait(context.id + 1, context.sync_id.semid_start  );

                // decremento il semaforo dei processi liberi
                sem_wait(SEMPROCFREE, context.sync_id.semid_sys);

                logsc(context.id, "Avvio...........OK\n");

                //-----------------------------------------------
                //      IMPOSTO LA FLAG DEL PROCESSO OCCUPATO
                //-----------------------------------------------
                sem_wait(MUTEXRES, context.sync_id.semid_sys);
                        context.shm_status[context.id].status = 0;
                sem_signal(MUTEXRES, context.sync_id.semid_sys);

                //-----------------------------------------------
                //      MEMORIZZO GLI OPERANDI PER IL CALCOLO
                //-----------------------------------------------
                read_operazione(&context);

                //-----------------------------------------------
                //      SEGNALO CHE MI SONO ARRIVATI I DATI
                //-----------------------------------------------
                sem_signal(SEMDATARECEIVE, context.sync_id.semid_sys );

                //-----------------------------------------------
                //      CONTROLLO CHE NON SIA IL SEGNALE KILL
                //-----------------------------------------------
                if(context.operazione_singola.kill == 'K'){
                        shm_detach(context.shm_operazione);
                        shm_detach(context.shm_status);
                        logsc(context.id, "Termino.........OK\n");
                        exit(0);
                }
                sprintf(str, "Dati arrivati...%d %c %d\n", context.operazione_singola.num1, context.operazione_singola.simbolo, context.operazione_singola.num2);
                logsc(context.id, str);

                //-----------------------------------------------
                //      CALCOLO IL RISULTATO
                //-----------------------------------------------
                calcolo_and_save_operazione(&context);

                //-----------------------------------------------
                //      SCRIVO I RISULTATI NELLA MEMORIA CONDIVISA
                //-----------------------------------------------
                sem_wait(MUTEXRES, context.sync_id.semid_sys  );
                        context.shm_status[context.id].status = 1;
                        context.shm_status[context.id].res = context.operazione_singola.res;
                        context.shm_status[context.id].pos = context.operazione_singola.pos;
                sem_signal(MUTEXRES, context.sync_id.semid_sys );
        }
        exit(0);
}// fine main
Exemplo n.º 8
0
int
main(int argc, char *argv[])
{
	struct radclock_handle *handle;
	struct radclock_config *conf;
	int is_daemon = 0;

	/* File and command line reading */
	int ch;
	
	/* Mask variable used to know which parameter to update */
	uint32_t param_mask = 0;

	/* PID lock file for daemon */
	int daemon_pid_fd 		= 0;

	/* Initialize PID lockfile to a default value */
	const char *pid_lockfile = DAEMON_LOCK_FILE;

	/* Misc */
	int err;

	/* turn off buffering to allow results to be seen immediately if JDEBUG*/
	#ifdef WITH_JDEBUG
	setvbuf(stdout, (char *)NULL, _IONBF, 0);
	setvbuf(stderr, (char *)NULL, _IONBF, 0);
	#endif

	/*
	 * Register Signal handlers. We use sigaction() instead of signal() to catch
	 * signals. The main reason concerns the SIGHUP signal. In Linux, the
	 * syscalls are restarted as soon as the signal handler returns. This
	 * prevent pcap_breakloop() to do its job (see pcap man page). Using
	 * sigaction() we can overwrite the default flag to prevent this behavior
	 */
	sigset_t block_mask;
	sigfillset (&block_mask);
	struct sigaction sig_struct;


	sig_struct.sa_handler = signal_handler;
	sig_struct.sa_mask = block_mask;
	sig_struct.sa_flags = 0;

	sigaction(SIGHUP,  &sig_struct, NULL); /* hangup signal (1) */
	sigaction(SIGTERM, &sig_struct, NULL); /* software termination signal (15) */
	sigaction(SIGUSR1, &sig_struct, NULL); /* user signal 1 (30) */
	sigaction(SIGUSR2, &sig_struct, NULL); /* user signal 2 (31) */


	/* Initialise verbose data to defaults */
	verbose_data.handle = NULL;
	verbose_data.is_daemon = 0;
	verbose_data.verbose_level = 0;
	verbose_data.fd = NULL;
	strcpy(verbose_data.logfile, "");
	pthread_mutex_init(&(verbose_data.vmutex), NULL);


	/* Management of configuration options */
	conf = (struct radclock_config *) malloc(sizeof(struct radclock_config));
	JDEBUG_MEMORY(JDBG_MALLOC, conf);
	memset(conf, 0, sizeof(struct radclock_config));

	/*
	 * The command line arguments are given the priority and override possible
	 * values of the configuration file But the configuration file is parsed
	 * after the command line because we need to know if we are running a daemon
	 * or not (configuration file is different if we run a daemon or not). Use
	 * the param_mask variable to indicate which values have to be updated from
	 * the config file
	 */

	/* Initialize the physical parameters, and other config parameters. */
	config_init(conf);

	/* Init the mask we use to signal configuration updates */
	param_mask = UPDMASK_NOUPD;

	/* Reading the command line arguments */
	while ((ch = getopt(argc, argv, "dxvhc:i:l:n:t:r:w:s:a:o:p:P:U:D:V")) != -1)
		switch (ch) {
		case 'x':
			SET_UPDATE(param_mask, UPDMASK_SERVER_IPC);
			conf->server_ipc = BOOL_OFF;
			break;
		case 'c':
			strcpy(conf->conffile, optarg);
			break;
		case 'd':
			is_daemon = 1;
			break;
		case 'l':
			strcpy(conf->logfile, optarg);
			break;
		case 'n':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_HOSTNAME);
			strcpy(conf->hostname, optarg);
			break;
		case 'p':
			SET_UPDATE(param_mask, UPDMASK_POLLPERIOD);
			if ( atoi(optarg) < RAD_MINPOLL ) {
				conf->poll_period = RAD_MINPOLL;
				fprintf(stdout, "Warning: Poll period too small, set to %d\n",
					conf->poll_period);
			}
			else
				conf->poll_period = atoi(optarg);
			if ( conf->poll_period > RAD_MAXPOLL ) {
				conf->poll_period = RAD_MAXPOLL;
				fprintf(stdout, "Warning: Poll period too big, set to %d\n",
						conf->poll_period);
			}
			break;
		case 't':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_TIME_SERVER);
			strcpy(conf->time_server, optarg);
			break;
		case 'i':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_NETWORKDEV);
			strcpy(conf->network_device, optarg);
			break;
		case 'r':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_SYNC_IN_PCAP);
			strcpy(conf->sync_in_pcap, optarg);
			break;
		case 'w':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_SYNC_OUT_PCAP);
			strcpy(conf->sync_out_pcap, optarg);
			break;
		case 's':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_SYNC_IN_ASCII);
			strcpy(conf->sync_in_ascii, optarg);
			break;
		case 'a':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_SYNC_OUT_ASCII);
			strcpy(conf->sync_out_ascii, optarg);
			break;
		case 'o':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_CLOCK_OUT_ASCII);
			strcpy(conf->clock_out_ascii, optarg);
			break;
		case 'P':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_PID_FILE);
			pid_lockfile = optarg;
			break;
		case 'v':
			SET_UPDATE(param_mask, UPDMASK_VERBOSE);
			conf->verbose_level++;
			break;
		case 'U':
			SET_UPDATE(param_mask, UPD_NTP_UPSTREAM_PORT);
			conf->ntp_upstream_port = atoi(optarg);
			break;
		case 'D':
			SET_UPDATE(param_mask, UPD_NTP_DOWNSTREAM_PORT);
			conf->ntp_downstream_port = atoi(optarg);
			break;
		case 'V':
			fprintf(stdout, "%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
		case 'h':
		case '?':
		default:
			usage();
		}

	argc -= optind;
	argv += optind;

	/* Little hack to deal with parsing of long options in the command line */
	if (conf->verbose_level > 0)
		SET_UPDATE(param_mask, UPDMASK_VERBOSE);


	/* Create the radclock handle */
	clock_handle = create_handle(conf, is_daemon);
	if (!clock_handle) {
		verbose(LOG_ERR, "Could not create clock handle");
		return (-1);
	}
	handle = clock_handle;


	/*
	 * Have not parsed the config file yet, so will have to do it again since it
	 * may not be the right settings. Handles config parse messages in the right
	 * log file though. So far clock has not been sent to init, no syscall
	 * registered, pass a NULL pointer to verbose.
	 */
	set_verbose(handle, handle->conf->verbose_level, 0);
	set_logger(logger_verbose_bridge);
	
	/* Daemonize now, so that we can open the log files and close connection to
	 * stdin since we parsed the command line
	 */
	if (handle->is_daemon) {
		struct stat sb;
		if (stat(RADCLOCK_RUN_DIRECTORY, &sb) < 0) {
			if (mkdir(RADCLOCK_RUN_DIRECTORY, 0755) < 0) {
				verbose(LOG_ERR, "Cannot create %s directory. Run as root or "
						"(!daemon && !server)", RADCLOCK_RUN_DIRECTORY);
				return (1);
			}
		}
		/* Check this everytime in case something happened */
		chmod(RADCLOCK_RUN_DIRECTORY, 00755);

		if (!(daemonize(pid_lockfile, &daemon_pid_fd))) {
			fprintf(stderr, "Error: did not manage to create the daemon\n");
			exit(EXIT_FAILURE);
		}
	}

	/*
	 * Retrieve configuration from the config file (write it down if it does not
	 * exist) That should be the only occasion when get_config() is called and
	 * the param_mask is not positioned to UPDMASK_NOUPD !!!  Only the
	 * parameters not specified on the command line are updated
	 */
	if (!config_parse(handle->conf, &param_mask, handle->is_daemon))
		return (0);

	/*
	 * Now that we have the configuration to use (verbose level),  let's
	 * initialise the verbose level to correct value
	 */
	set_verbose(handle, handle->conf->verbose_level, 0);
	set_logger(logger_verbose_bridge);

	/* Check for incompatible configurations and correct them */
	if (( handle->conf->synchro_type == SYNCTYPE_SPY ) ||
		( handle->conf->synchro_type == SYNCTYPE_PIGGY ))
	{
		if (handle->conf->server_ntp == BOOL_ON) {
			verbose(LOG_ERR, "Configuration error. Disabling NTP server "
					"(incompatible with spy or piggy mode).");
			handle->conf->server_ntp = BOOL_OFF;
		}
		if ( handle->conf->adjust_sysclock == BOOL_ON )
		{
			verbose(LOG_ERR, "Configuration error. Disabling adjust system "
					"clock (incompatible with spy or piggy mode).");
			handle->conf->adjust_sysclock = BOOL_OFF;
		}
	}
	
	/* Diagnosis output for the configuration used */
	config_print(LOG_NOTICE, handle->conf);

	/* Reinit the mask that counts updated values */
	param_mask = UPDMASK_NOUPD;


	// TODO extract extra checks from is_live_source and make an input fix 
	// function instead, would be clearer
	// TODO the conf->network_device business is way too messy


	/*
	 * Need to know if we are replaying data or not. If not, no need to create
	 * shared global data on the system or open a BPF. This define input to the
	 * init of the radclock handle
	 */
	if (!is_live_source(handle))
		handle->run_mode = RADCLOCK_SYNC_DEAD;
	else
		handle->run_mode = RADCLOCK_SYNC_LIVE;

	/* Init clock handle and private data */
	if (handle->run_mode == RADCLOCK_SYNC_LIVE) {
		err = clock_init_live(handle->clock, &handle->rad_data);
		if (err) {
			verbose(LOG_ERR, "Could not initialise the RADclock");
			return (1);
		}
	}

	/* Init radclock specific stuff */
	err = init_handle(handle);
	if (err) {
		verbose(LOG_ERR, "Radclock process specific init failed.");
		return (1);
	}

	/*
	 * Now 2 cases. Either we are running live or we are replaying some data.
	 * If we run live, we will spawn some threads and do some smart things.  If
	 * we replay data, no need to do all of that, we access data and process it
	 * in the same thread.
	 */
	if (handle->run_mode == RADCLOCK_SYNC_DEAD) {

// TODO : manage peers better !!

		struct bidir_peer peer;
		/* Some basic initialisation which is required */
		init_peer_stamp_queue(&peer);
		peer.stamp_i = 0;
		// TODO XXX Need to manage peers better !!
		/* Register active peer */
		handle->active_peer = (void *)&peer;
		while (1) {
			err = process_rawdata(handle, &peer);
			if (err < 0)
				break;
		}

		destroy_peer_stamp_queue(&peer);
	}

	/*
	 * We loop in here in case we are rehashed. Threads are (re-)created every
	 * time we loop in
	 */
	else {
		while (err == 0) {
			err = start_live(handle);
			if (err == 0) {
				if (rehash_daemon(handle, param_mask))
					verbose(LOG_ERR, "SIGHUP - Failed to rehash daemon !!.");
			}
		}
	}


	// TODO: look into making the stats a separate structure. Could be much
	// TODO: easier to manage
	long int n_stamp;
	unsigned int ref_count;
	n_stamp = ((struct bidir_output *)handle->algo_output)->n_stamps;
	ref_count = ((struct stampsource*)(handle->stamp_source))->ntp_stats.ref_count;
	verbose(LOG_NOTICE, "%u NTP packets captured", ref_count);
	verbose(LOG_NOTICE,"%ld missed NTP packets", ref_count - 2 * n_stamp);
	verbose(LOG_NOTICE, "%ld valid timestamp tuples extracted", n_stamp);

	/* Close output files */
	close_output_stamp(handle);

	/* Print out last good phat value */
	verbose(LOG_NOTICE, "Last estimate of the clock source period: %12.10lg",
			RAD_DATA(handle)->phat);

	/* Say bye and close syslog */
	verbose(LOG_NOTICE, "RADclock stopped");
	if (handle->is_daemon)
		closelog ();
	unset_verbose();

	/* Free the lock file */
	if (handle->is_daemon) {
		write(daemon_pid_fd, "", 0);
		lockf(daemon_pid_fd, F_ULOCK, 0);
	}

	// TODO:  all the destructors have to be re-written
	destroy_source(handle, (struct stampsource *)(handle->stamp_source));


	/* Clear thread stuff */
	pthread_mutex_destroy(&(handle->globaldata_mutex));
	pthread_mutex_destroy(&(handle->wakeup_mutex));
	pthread_cond_destroy(&(handle->wakeup_cond));

	/* Detach IPC shared memory if were running as IPC server. */
	if (handle->conf->server_ipc == BOOL_ON)
		shm_detach(handle->clock);

	/* Free the clock structure. All done. */
	pthread_mutex_destroy(&(handle->pcap_queue->rdb_mutex));
	pthread_mutex_destroy(&(handle->ieee1588eq_queue->rdb_mutex));
	free(handle->pcap_queue);
	free(handle->ieee1588eq_queue);
	free(handle);
	handle = NULL;
	clock_handle = NULL;

	exit(EXIT_SUCCESS);
}
Exemplo n.º 9
0
// TODO : Reload of individual physical parameters is not handled
static int
rehash_daemon(struct radclock_handle *handle, uint32_t param_mask)
{
	struct radclock_config *conf;
	int err;

	JDEBUG

	conf = handle->conf;

	verbose(LOG_NOTICE, "Update of configuration parameters");
	/* Parse the configuration file */
	if (!(config_parse(conf, &param_mask, handle->is_daemon))) {
		verbose(LOG_ERR, "Error: Rehash of configuration file failed");
		return (1);
	}
	
	if (HAS_UPDATE(param_mask, UPDMASK_SYNCHRO_TYPE))
		verbose(LOG_WARNING, "It is not possible to change the type of client "
				"synchronisation on the fly!");
	
	//XXX Should check we have only one input selected
	if (HAS_UPDATE(param_mask, UPDMASK_NETWORKDEV) ||
			HAS_UPDATE(param_mask, UPDMASK_SYNC_IN_PCAP) ||
			HAS_UPDATE(param_mask, UPDMASK_SYNC_IN_ASCII))
	{
		verbose(LOG_WARNING, "It is not possible to change the type of input "
				"on the fly!");
		verbose(LOG_WARNING, "Parameter is parsed and saved but not taken "
				"into account");
		CLEAR_UPDATE(param_mask, UPDMASK_NETWORKDEV);
		CLEAR_UPDATE(param_mask, UPDMASK_SYNC_IN_PCAP);
		CLEAR_UPDATE(param_mask, UPDMASK_SYNC_IN_ASCII);
	}

// TODO The old naming convention for server IPC could be changed for clarity.
// Would require an update of config file parsing.
	if (HAS_UPDATE(param_mask, UPDMASK_SERVER_IPC)) {
		switch (conf->server_ipc) {
		case BOOL_ON:
			err = shm_init_writer(handle->clock);
			if (err)
				return (1);
			verbose(LOG_NOTICE, "IPC Shared Memory ready");
			break;
		case BOOL_OFF:
			/* Detach for SHM segment, but do not destroy it */
			shm_detach(handle->clock);
			break;
		}
	}

	if (HAS_UPDATE(param_mask, UPDMASK_SERVER_NTP)) {
		switch (conf->server_ntp) {
		case BOOL_ON:
			/* We start NTP server */
			start_thread_NTP_SERV(handle);
			break;
		case BOOL_OFF:
			/* We stop the NTP server */
			handle->pthread_flag_stop |= PTH_NTP_SERV_STOP;
// TODO should we join the thread in here ... requires testing
//			pthread_join(handle->threads[PTH_NTP_SERV], &thread_status);
			break;
		}
	}

	if (HAS_UPDATE(param_mask, UPDMASK_SERVER_VM_UDP)) {
		switch (conf->server_vm_udp) {
		case BOOL_ON:	
			/* We start NTP server */
			start_thread_VM_UDP_SERV(handle);
			break;
		case BOOL_OFF:
			/* We stop the NTP server */
			clock_handle->pthread_flag_stop |= PTH_VM_UDP_SERV_STOP; 
// TODO should we join the thread in here ... requires testing
//			pthread_join(clock_handle->threads[PTH_VM_UDP_SERV], &thread_status);
			break;
		}
	}

	/* Management of output files */
	if (HAS_UPDATE(param_mask, UPDMASK_SYNC_OUT_ASCII)) {
		close_output_stamp(handle);
		open_output_stamp(handle);
		CLEAR_UPDATE(param_mask, UPDMASK_SYNC_OUT_ASCII);
	}

	if (HAS_UPDATE(param_mask, UPDMASK_CLOCK_OUT_ASCII)) {
		close_output_matlab(handle);
		open_output_matlab(handle);
		CLEAR_UPDATE(param_mask, UPDMASK_CLOCK_OUT_ASCII);
	}

	if (HAS_UPDATE(param_mask, UPDMASK_SYNC_OUT_PCAP)) {
		err = update_dumpout_source(handle, (struct stampsource *)handle->stamp_source);
		if (err != 0) {
			verbose(LOG_ERR, "Things are probably out of control. Bye !");
			exit (1);
		}
		CLEAR_UPDATE(param_mask, UPDMASK_SYNC_OUT_PCAP);
	}


	/* Change the filter on the open BPF device */
	if (HAS_UPDATE(param_mask, UPDMASK_SYNCHRO_TYPE) ||
			HAS_UPDATE(param_mask, UPDMASK_SERVER_NTP) ||
			HAS_UPDATE(param_mask, UPDMASK_TIME_SERVER) ||
			HAS_UPDATE(param_mask, UPDMASK_HOSTNAME))
	{
		err = update_filter_source(handle, (struct stampsource *)handle->stamp_source);
		if (err != 0)  {
			verbose(LOG_ERR, "Things are probably out of control. Bye !");
			exit (1);
		}
		CLEAR_UPDATE(param_mask, UPDMASK_TIME_SERVER);
		CLEAR_UPDATE(param_mask, UPDMASK_HOSTNAME);
	}

	/*  Print configuration actually used */
	config_print(LOG_NOTICE, conf);

	/* Reinit rehash flag */
//	handle->unix_signal = 0;

	/* Push param_mask into the config so that the algo sees it,
	 * since only algo related thing should be remaining
	 */
	conf->mask = param_mask;

	return (0);
}