/** * 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); } } } }
/** 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; }
static void shm_close(void *addr) { shm_detach(addr); shm_rm(); }
/*** Detach from a shared memory area ***/ void _0x94_shm_detach(void) { shm_detach(current_process); current_process->state = READY; }
/** * 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; }
/** 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); }
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
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, ¶m_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); }
// 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, ¶m_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); }