/** * @NOTE if #flags.protocol_version is CF_PROTOCOL_UNDEFINED, then classic * protocol is used by default. */ AgentConnection *ServerConnection(const char *server, const char *port, unsigned int connect_timeout, ConnectionFlags flags, int *err) { AgentConnection *conn = NULL; int ret; *err = 0; conn = NewAgentConn(server, port, flags); #if !defined(__MINGW32__) signal(SIGPIPE, SIG_IGN); sigset_t signal_mask; sigemptyset(&signal_mask); sigaddset(&signal_mask, SIGPIPE); pthread_sigmask(SIG_BLOCK, &signal_mask, NULL); /* FIXME: username is local */ GetCurrentUserName(conn->username, sizeof(conn->username)); #else /* Always say "root" as username from windows. */ strlcpy(conn->username, "root", sizeof(conn->username)); #endif if (port == NULL || *port == '\0') { port = CFENGINE_PORT_STR; } char txtaddr[CF_MAX_IP_LEN] = ""; conn->conn_info->sd = SocketConnect(server, port, connect_timeout, flags.force_ipv4, txtaddr, sizeof(txtaddr)); if (conn->conn_info->sd == -1) { Log(LOG_LEVEL_INFO, "No server is responding on port: %s", port); DisconnectServer(conn); *err = -1; return NULL; } assert(sizeof(conn->remoteip) >= sizeof(txtaddr)); strcpy(conn->remoteip, txtaddr); switch (flags.protocol_version) { case CF_PROTOCOL_UNDEFINED: case CF_PROTOCOL_TLS: /* Set the version to request during protocol negotiation. After * TLSConnect() it will have the version we finally ended up with. */ conn->conn_info->protocol = CF_PROTOCOL_LATEST; ret = TLSConnect(conn->conn_info, flags.trust_server, conn->remoteip, conn->username); if (ret == -1) /* Error */ { DisconnectServer(conn); *err = -1; return NULL; } else if (ret == 0) /* Auth/ID error */ { DisconnectServer(conn); errno = EPERM; *err = -2; return NULL; } assert(ret == 1); conn->conn_info->status = CONNECTIONINFO_STATUS_ESTABLISHED; LastSaw1(conn->remoteip, KeyPrintableHash(conn->conn_info->remote_key), LAST_SEEN_ROLE_CONNECT); break; case CF_PROTOCOL_CLASSIC: conn->conn_info->protocol = CF_PROTOCOL_CLASSIC; conn->encryption_type = CfEnterpriseOptions(); if (!IdentifyAgent(conn->conn_info)) { Log(LOG_LEVEL_ERR, "Id-authentication for '%s' failed", VFQNAME); errno = EPERM; DisconnectServer(conn); *err = -2; // auth err return NULL; } if (!AuthenticateAgent(conn, flags.trust_server)) { Log(LOG_LEVEL_ERR, "Authentication dialogue with '%s' failed", server); errno = EPERM; DisconnectServer(conn); *err = -2; // auth err return NULL; } conn->conn_info->status = CONNECTIONINFO_STATUS_ESTABLISHED; break; default: ProgrammingError("ServerConnection: ProtocolVersion %d!", flags.protocol_version); } conn->authenticated = true; return conn; }
virtual void requestInit() { handlers.reset(); // restore the old signal mask, thus unblock those that should be pthread_sigmask(SIG_SETMASK, &oldSet, NULL); }
static void *clamuko_scanth(void *arg) { struct thrarg *tharg = (struct thrarg *) arg; sigset_t sigset; unsigned int sizelimit = 0; struct stat sb; dazukofs_handle_t scan_hndl; struct dazukofs_access acc; const char *groupname = "ClamAV"; int skip_scan = 0; const char *virname; char filename[4096]; /* ignore all signals */ sigfillset(&sigset); /* The behavior of a process is undefined after it ignores a * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ sigdelset(&sigset, SIGFPE); sigdelset(&sigset, SIGILL); sigdelset(&sigset, SIGSEGV); #ifdef SIGBUS sigdelset(&sigset, SIGBUS); #endif pthread_sigmask(SIG_SETMASK, &sigset, NULL); /* register */ scan_hndl = dazukofs_open(groupname, DAZUKOFS_TRACK_GROUP); if(!scan_hndl) { logg("!Clamuko: Can't register with DazukoFS\n"); return NULL; } else { logg("Clamuko: Correctly registered with DazukoFS.\n"); } /* access mask (not used by DazukoFS) */ if(optget(tharg->opts, "ClamukoScanOnOpen")->enabled) logg("!Clamuko: ClamukoScanOnOpen ignored when using DazukoFS.\n"); if(optget(tharg->opts, "ClamukoScanOnClose")->enabled) logg("!Clamuko: ClamukoScanOnClose ignored when using DazukoFS.\n"); if(optget(tharg->opts, "ClamukoScanOnExec")->enabled) logg("!Clamuko: ClamukoScanOnExec ignored when using DazukoFS.\n"); if(optget(tharg->opts, "ClamukoIncludePath")->enabled) logg("!Clamuko: ClamukoIncludePath ignored when using DazukoFS.\n"); if(optget(tharg->opts, "ClamukoExcludePath")->enabled) logg("!Clamuko: ClamukoExcludePath ignored when using DazukoFS.\n"); sizelimit = optget(tharg->opts, "ClamukoMaxFileSize")->numarg; if(sizelimit) logg("Clamuko: Max file size limited to %u bytes.\n", sizelimit); else logg("Clamuko: File size limit disabled.\n"); while(1) { if(dazukofs_get_access(scan_hndl, &acc)) { if(!shutdown_hndl) break; continue; } if(!fstat(acc.fd, &sb)) { if(S_ISDIR(sb.st_mode)) { /* don't try to scan directories */ skip_scan = 1; } else if(sb.st_size > sizelimit) { dazukofs_get_filename(&acc, filename, sizeof(filename)); logg("*Clamuko: %s skipped (too big)\n", filename); skip_scan = 1; } } if(skip_scan) { acc.deny = 0; /* reset skip flag */ skip_scan = 0; } else if(cl_scandesc(acc.fd, &virname, NULL, tharg->engine, tharg->options) == CL_VIRUS) { dazukofs_get_filename(&acc, filename, sizeof(filename)); logg("Clamuko: %s: %s FOUND\n", filename, virname); /* we can not perform any special action because it will * trigger DazukoFS recursively */ acc.deny = 1; } else { acc.deny = 0; } if(dazukofs_return_access(scan_hndl, &acc)) { if(shutdown_hndl) logg("!Clamuko: Can't return access to DazukoFS.\n"); break; } } dazukofs_close(scan_hndl, 0); if(shutdown_hndl) logg("!Clamuko: A scanner thread has unexpectedly shutdown.\n"); return NULL; }
/** * Main function, starts the conftest daemon. */ int main(int argc, char *argv[]) { struct sigaction action; int status = 0; sigset_t set; int sig; char *suite_file = "suite.conf", *test_file = NULL, *preload, *plugins; file_logger_t *logger; if (!library_init(NULL, "conftest")) { library_deinit(); return SS_RC_LIBSTRONGSWAN_INTEGRITY; } if (!libhydra_init()) { libhydra_deinit(); library_deinit(); return SS_RC_INITIALIZATION_FAILED; } if (!libcharon_init()) { libcharon_deinit(); libhydra_deinit(); library_deinit(); return SS_RC_INITIALIZATION_FAILED; } INIT(conftest, .creds = mem_cred_create(), .config = config_create(), .hooks = linked_list_create(), .loggers = linked_list_create(), ); lib->credmgr->add_set(lib->credmgr, &conftest->creds->set); logger = file_logger_create("stdout"); logger->set_options(logger, NULL, FALSE); logger->open(logger, FALSE, FALSE); logger->set_level(logger, DBG_ANY, LEVEL_CTRL); charon->bus->add_logger(charon->bus, &logger->logger); conftest->loggers->insert_last(conftest->loggers, logger); atexit(cleanup); while (TRUE) { struct option long_opts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "suite", required_argument, NULL, 's' }, { "test", required_argument, NULL, 't' }, { 0,0,0,0 } }; switch (getopt_long(argc, argv, "", long_opts, NULL)) { case EOF: break; case 'h': usage(stdout); return 0; case 'v': printf("strongSwan %s conftest\n", VERSION); return 0; case 's': suite_file = optarg; continue; case 't': test_file = optarg; continue; default: usage(stderr); return 1; } break; } if (!load_configs(suite_file, test_file)) { return 1; } load_loggers(logger); preload = conftest->test->get_str(conftest->test, "preload", ""); if (asprintf(&plugins, "%s %s", preload, PLUGINS) < 0) { return 1; } if (!charon->initialize(charon, plugins)) { free(plugins); return 1; } lib->plugins->status(lib->plugins, LEVEL_CTRL); free(plugins); if (!load_certs(conftest->test, conftest->suite_dir)) { return 1; } if (!load_keys(conftest->test, conftest->suite_dir)) { return 1; } load_cdps(conftest->test); if (!load_hooks()) { return 1; } charon->backends->add_backend(charon->backends, &conftest->config->backend); conftest->config->load(conftest->config, conftest->test); conftest->actions = actions_create(); /* set up thread specific handlers */ action.sa_handler = segv_handler; action.sa_flags = 0; sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGINT); sigaddset(&action.sa_mask, SIGTERM); sigaddset(&action.sa_mask, SIGHUP); sigaction(SIGSEGV, &action, NULL); sigaction(SIGILL, &action, NULL); sigaction(SIGBUS, &action, NULL); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL); /* start thread pool */ charon->start(charon); /* handle SIGINT/SIGTERM in main thread */ sigemptyset(&set); sigaddset(&set, SIGINT); sigaddset(&set, SIGHUP); sigaddset(&set, SIGTERM); sigprocmask(SIG_BLOCK, &set, NULL); while ((sig = sigwaitinfo(&set, NULL)) != -1) { switch (sig) { case SIGINT: case SIGTERM: fprintf(stderr, "\nshutting down...\n"); break; default: continue; } break; } return status; }
void uv__io_poll(uv_loop_t* loop, int timeout) { struct port_event events[1024]; struct port_event* pe; struct timespec spec; QUEUE* q; uv__io_t* w; sigset_t* pset; sigset_t set; uint64_t base; uint64_t diff; unsigned int nfds; unsigned int i; int saved_errno; int nevents; int count; int err; int fd; if (loop->nfds == 0) { assert(QUEUE_EMPTY(&loop->watcher_queue)); return; } while (!QUEUE_EMPTY(&loop->watcher_queue)) { q = QUEUE_HEAD(&loop->watcher_queue); QUEUE_REMOVE(q); QUEUE_INIT(q); w = QUEUE_DATA(q, uv__io_t, watcher_queue); assert(w->pevents != 0); if (port_associate(loop->backend_fd, PORT_SOURCE_FD, w->fd, w->pevents, 0)) abort(); w->events = w->pevents; } pset = NULL; if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { pset = &set; sigemptyset(pset); sigaddset(pset, SIGPROF); } assert(timeout >= -1); base = loop->time; count = 48; /* Benchmarks suggest this gives the best throughput. */ for (;;) { if (timeout != -1) { spec.tv_sec = timeout / 1000; spec.tv_nsec = (timeout % 1000) * 1000000; } /* Work around a kernel bug where nfds is not updated. */ events[0].portev_source = 0; nfds = 1; saved_errno = 0; if (pset != NULL) pthread_sigmask(SIG_BLOCK, pset, NULL); err = port_getn(loop->backend_fd, events, ARRAY_SIZE(events), &nfds, timeout == -1 ? NULL : &spec); if (pset != NULL) pthread_sigmask(SIG_UNBLOCK, pset, NULL); if (err) { /* Work around another kernel bug: port_getn() may return events even * on error. */ if (errno == EINTR || errno == ETIME) saved_errno = errno; else abort(); } /* Update loop->time unconditionally. It's tempting to skip the update when * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the * operating system didn't reschedule our process while in the syscall. */ SAVE_ERRNO(uv__update_time(loop)); if (events[0].portev_source == 0) { if (timeout == 0) return; if (timeout == -1) continue; goto update_timeout; } if (nfds == 0) { assert(timeout != -1); return; } nevents = 0; assert(loop->watchers != NULL); loop->watchers[loop->nwatchers] = (void*)events; loop->watchers[loop->nwatchers + 1] = (void*)(uintptr_t)nfds; for (i = 0; i < nfds; i++) { pe = events + i; fd = pe->portev_object; /* Skip invalidated events, see uv__platform_invalidate_fd */ if (fd == -1) continue; assert(fd >= 0); assert((unsigned)fd < loop->nwatchers); w = loop->watchers[fd]; /* File descriptor that we've stopped watching, ignore. */ if (w == NULL) continue; w->cb(loop, w, pe->portev_events); nevents++; /* Events Ports operates in oneshot mode, rearm timer on next run. */ if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue)) QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); } loop->watchers[loop->nwatchers] = NULL; loop->watchers[loop->nwatchers + 1] = NULL; if (nevents != 0) { if (nfds == ARRAY_SIZE(events) && --count != 0) { /* Poll for more events but don't block this time. */ timeout = 0; continue; } return; } if (saved_errno == ETIME) { assert(timeout != -1); return; } if (timeout == 0) return; if (timeout == -1) continue; update_timeout: assert(timeout > 0); diff = loop->time - base; if (diff >= (uint64_t)timeout) return; timeout -= diff; } }
int main( int argc, char **argv ) { int sig; sigset_t termSig; pthread_t readSerialThreadId; pthread_t readStdinThreadId; int rc; int opt; const char *baudStr = NULL; #if defined( linux ) const char *portStr = "ttyS0"; #else const char *portStr = "com1"; #endif #if USE_I2C PKT_TextChar = PacketTextChar; PKT_SendChar = PacketSendChar; PKT_PacketReceived = PacketReceived; #endif // signal( SIGINT, ControlC ); // signal( SIGTERM, ControlC ); LogInit( stdout ); while (( opt = getopt_long( argc, argv, "b:dhmp:sv", gLongOption, NULL )) > 0 ) { switch ( opt ) { case 'b': { baudStr = optarg; break; } case 'd': { gDebug = true; break; } case 'g': { gDongle = true; break; } case 'm': { gMegaLoad = true; break; } case 'p': { portStr = optarg; break; } case 'r': { gUseRtsToReset = true; break; } case 's': { gStk500 = true; break; } case 'v': { gVerbose = true; break; } #if USE_I2C case OPT_DEBUG_DONGLE: { gSerialDongle.m_debugDongle = true; break; } case OPT_DEBUG_DONGLE_DATA: { gSerialDongle.m_debugDongleData = true; break; } #endif case '?': case 'h': { Usage(); return 1; } } } if ( optind < argc ) { if (( optind + 1 ) != argc ) { fprintf( stderr, "Only one download file supported\n" ); return 1; } gDownloadFileName = argv[ optind ]; } // Open the file to download if ( gDownloadFileName != NULL ) { // If we are asked to download a file, then read the entire file // into memory. if (( gDownloadInfo = ReadFile( gDownloadFileName )) == NULL ) { return 1; } } if ( !gSerialPort.Open( portStr, baudStr )) { return 1; } gSerialPort.UseRTStoReset( gUseRtsToReset ); gSerialPort.ResetTarget(); // Put stdin in raw mode setbuf( stdin, NULL ); setbuf( stdout, NULL ); #if defined( unix ) sigemptyset( &termSig ); sigaddset( &termSig, SIGINT ); sigaddset( &termSig, SIGTERM ); pthread_sigmask( SIG_BLOCK, &termSig, NULL ); struct termios tio_new; if ( tcgetattr( fileno( stdin ), &gTio_org ) < 0 ) { LogError( "Unable to retrieve terminal settings\n" ); return 1; } tio_new = gTio_org; tio_new.c_lflag &= ~( ICANON | ECHO ); tio_new.c_cc[VMIN] = 1; tio_new.c_cc[VTIME] = 0; if ( tcsetattr( fileno( stdin ), TCSANOW, &tio_new ) < 0 ) { LogError( "Unable to update terminal settings\n" ); return 1; } #endif const char *bootLoaderType = "*** Unknown ***"; if ( gDongle ) { bootLoaderType = "Serial Dongle"; } else if ( gMegaLoad ) { bootLoaderType = "MegaLoad v2.3"; } else if ( gStk500 ) { bootLoaderType = "STK500"; } gLogFs2 = fopen( "BootHost.log", "wb" ); Log( "BootHost - BootLoader: %s\n", bootLoaderType ); // Kick off the serial port reader thread. rc = pthread_create( &readSerialThreadId, NULL, ReadSerialThread, &gSerialPort ); if ( rc != 0 ) { fprintf( stderr, "Error creating ReadSerialThread: %d\n", rc ); return 1; } // Kick off the stdin reader thread. rc = pthread_create( &readStdinThreadId, NULL, ReadStdinThread, NULL ); if ( rc != 0 ) { fprintf( stderr, "Error creating ReadSerialThread: %d\n", rc ); return 1; } #if defined( unix ) // Wait for a termmination signal if (( rc = sigwait( &termSig, &sig )) != 0 ) { fprintf( stderr, "sigwait failed\n" ); } else { fprintf( stderr, "Exiting...\n" ); } pthread_cancel( readSerialThreadId ); pthread_cancel( readStdinThreadId ); // Restore stdin back to the way it was when we started if ( tcsetattr( fileno( stdin ), TCSANOW, &gTio_org ) == -1 ) { LogError( "Unable to restore terminal settings\n" ); } #endif #if defined( __CYGWIN__ ) // Under Windows closing the serial port and stdin will cause the reads // to unblock. Under linux, this isn't required, but it doesn't hurt // either. gSerialPort.Close(); fclose( stdin ); #endif // Unblock the termination signals so the user can kill us if we hang up // waiting for the reader threads to exit. #if defined( unix ) pthread_sigmask( SIG_UNBLOCK, &termSig, NULL ); #endif pthread_join( readSerialThreadId, NULL ); pthread_join( readStdinThreadId, NULL ); #if !defined( __CYGWIN__ ) gSerialPort.Close(); fclose( stdin ); #endif if ( gVerbose ) { printf( "Done\n" ); } return 0; } // main
int main(int argc, char **argv) { int i; sigset_t set; #if ENABLE_MPEGTS uint32_t adapter_mask = 0; #endif int log_level = LOG_INFO; int log_options = TVHLOG_OPT_MILLIS | TVHLOG_OPT_STDERR | TVHLOG_OPT_SYSLOG; const char *log_debug = NULL, *log_trace = NULL; gid_t gid = -1; uid_t uid = -1; char buf[512]; FILE *pidfile = NULL; extern int dvb_bouquets_parse; main_tid = pthread_self(); /* Setup global mutexes */ pthread_mutex_init(&fork_lock, NULL); pthread_mutex_init(&global_lock, NULL); pthread_mutex_init(&tasklet_lock, NULL); pthread_mutex_init(&atomic_lock, NULL); pthread_cond_init(>imer_cond, NULL); pthread_cond_init(&tasklet_cond, NULL); TAILQ_INIT(&tasklets); /* Defaults */ tvheadend_webui_port = 9981; tvheadend_webroot = NULL; tvheadend_htsp_port = 9982; tvheadend_htsp_port_extra = 0; time(&dispatch_clock); /* Command line options */ int opt_help = 0, opt_version = 0, opt_fork = 0, opt_firstrun = 0, opt_stderr = 0, opt_syslog = 0, opt_nosyslog = 0, opt_uidebug = 0, opt_abort = 0, opt_noacl = 0, opt_fileline = 0, opt_threadid = 0, opt_libav = 0, opt_ipv6 = 0, opt_satip_rtsp = 0, #if ENABLE_TSFILE opt_tsfile_tuner = 0, #endif opt_dump = 0, opt_xspf = 0, opt_dbus = 0, opt_dbus_session = 0, opt_nobackup = 0, opt_nobat = 0; const char *opt_config = NULL, *opt_user = NULL, *opt_group = NULL, *opt_logpath = NULL, *opt_log_debug = NULL, *opt_log_trace = NULL, *opt_pidpath = "/var/run/tvheadend.pid", #if ENABLE_LINUXDVB *opt_dvb_adapters = NULL, #endif *opt_bindaddr = NULL, *opt_subscribe = NULL, *opt_user_agent = NULL; str_list_t opt_satip_xml = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) }; str_list_t opt_tsfile = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) }; cmdline_opt_t cmdline_opts[] = { { 0, NULL, N_("Generic Options"), OPT_BOOL, NULL }, { 'h', "help", N_("Show this page"), OPT_BOOL, &opt_help }, { 'v', "version", N_("Show version information"),OPT_BOOL, &opt_version }, { 0, NULL, N_("Service Configuration"), OPT_BOOL, NULL }, { 'c', "config", N_("Alternate config path"), OPT_STR, &opt_config }, { 'B', "nobackup", N_("Don't backup config tree at upgrade"), OPT_BOOL, &opt_nobackup }, { 'f', "fork", N_("Fork and run as daemon"), OPT_BOOL, &opt_fork }, { 'u', "user", N_("Run as user"), OPT_STR, &opt_user }, { 'g', "group", N_("Run as group"), OPT_STR, &opt_group }, { 'p', "pid", N_("Alternate pid path"), OPT_STR, &opt_pidpath }, { 'C', "firstrun", N_("If no user account exists then create one with\n" "no username and no password. Use with care as\n" "it will allow world-wide administrative access\n" "to your Tvheadend installation until you edit/create\n" "access-control from within the Tvheadend UI"), OPT_BOOL, &opt_firstrun }, #if ENABLE_DBUS_1 { 'U', "dbus", N_("Enable DBus"), OPT_BOOL, &opt_dbus }, { 'e', "dbus_session", N_("DBus - use the session message bus instead system one"), OPT_BOOL, &opt_dbus_session }, #endif #if ENABLE_LINUXDVB { 'a', "adapters", N_("Only use specified DVB adapters (comma separated)"), OPT_STR, &opt_dvb_adapters }, #endif #if ENABLE_SATIP_SERVER { 0, "satip_rtsp", N_("SAT>IP RTSP port number for server\n" "(default: -1 = disable, 0 = webconfig, standard port is 554)"), OPT_INT, &opt_satip_rtsp }, #endif #if ENABLE_SATIP_CLIENT { 0, "satip_xml", N_("URL with the SAT>IP server XML location"), OPT_STR_LIST, &opt_satip_xml }, #endif { 0, NULL, N_("Server Connectivity"), OPT_BOOL, NULL }, { '6', "ipv6", N_("Listen on IPv6"), OPT_BOOL, &opt_ipv6 }, { 'b', "bindaddr", N_("Specify bind address"), OPT_STR, &opt_bindaddr}, { 0, "http_port", N_("Specify alternative http port"), OPT_INT, &tvheadend_webui_port }, { 0, "http_root", N_("Specify alternative http webroot"), OPT_STR, &tvheadend_webroot }, { 0, "htsp_port", N_("Specify alternative htsp port"), OPT_INT, &tvheadend_htsp_port }, { 0, "htsp_port2", N_("Specify extra htsp port"), OPT_INT, &tvheadend_htsp_port_extra }, { 0, "useragent", N_("Specify User-Agent header for the http client"), OPT_STR, &opt_user_agent }, { 0, "xspf", N_("Use XSPF playlist instead of M3U"), OPT_BOOL, &opt_xspf }, { 0, NULL, N_("Debug Options"), OPT_BOOL, NULL }, { 'd', "stderr", N_("Enable debug on stderr"), OPT_BOOL, &opt_stderr }, { 's', "syslog", N_("Enable debug to syslog"), OPT_BOOL, &opt_syslog }, { 'S', "nosyslog", N_("Disable syslog (all msgs)"), OPT_BOOL, &opt_nosyslog }, { 'l', "logfile", N_("Enable debug to file"), OPT_STR, &opt_logpath }, { 0, "debug", N_("Enable debug subsystems"), OPT_STR, &opt_log_debug }, #if ENABLE_TRACE { 0, "trace", N_("Enable trace subsystems"), OPT_STR, &opt_log_trace }, #endif { 0, "fileline", N_("Add file and line numbers to debug"), OPT_BOOL, &opt_fileline }, { 0, "threadid", N_("Add the thread ID to debug"), OPT_BOOL, &opt_threadid }, #if ENABLE_LIBAV { 0, "libav", N_("More verbose libav log"), OPT_BOOL, &opt_libav }, #endif { 0, "uidebug", N_("Enable webUI debug (non-minified JS)"), OPT_BOOL, &opt_uidebug }, { 'A', "abort", N_("Immediately abort"), OPT_BOOL, &opt_abort }, { 'D', "dump", N_("Enable coredumps for daemon"), OPT_BOOL, &opt_dump }, { 0, "noacl", N_("Disable all access control checks"), OPT_BOOL, &opt_noacl }, { 0, "nobat", N_("Disable DVB bouquets"), OPT_BOOL, &opt_nobat }, { 'j', "join", N_("Subscribe to a service permanently"), OPT_STR, &opt_subscribe }, #if ENABLE_TSFILE || ENABLE_TSDEBUG { 0, NULL, N_("Testing options"), OPT_BOOL, NULL }, { 0, "tsfile_tuners", N_("Number of tsfile tuners"), OPT_INT, &opt_tsfile_tuner }, { 0, "tsfile", N_("tsfile input (mux file)"), OPT_STR_LIST, &opt_tsfile }, #endif #if ENABLE_TSDEBUG { 0, "tsdebug", N_("Output directory for tsdebug"), OPT_STR, &tvheadend_tsdebug }, #endif }; /* Get current directory */ tvheadend_cwd0 = dirname(tvh_strdupa(argv[0])); tvheadend_cwd = dirname(tvh_strdupa(tvheadend_cwd0)); /* Set locale */ setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, "C"); tvh_gettext_init(); /* make sure the timezone is set */ tzset(); /* Process command line */ for (i = 1; i < argc; i++) { /* Find option */ cmdline_opt_t *opt = cmdline_opt_find(cmdline_opts, ARRAY_SIZE(cmdline_opts), argv[i]); if (!opt) show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), _("invalid option specified [%s]"), argv[i]); /* Process */ if (opt->type == OPT_BOOL) *((int*)opt->param) = 1; else if (++i == argc) show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), _("option %s requires a value"), opt->lopt); else if (opt->type == OPT_INT) *((int*)opt->param) = atoi(argv[i]); else if (opt->type == OPT_STR_LIST) { str_list_t *strl = opt->param; if (strl->num < strl->max) strl->str[strl->num++] = argv[i]; } else *((char**)opt->param) = argv[i]; /* Stop processing */ if (opt_help) show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), NULL); if (opt_version) show_version(argv[0]); } /* Additional cmdline processing */ if (opt_nobat) dvb_bouquets_parse = 0; #if ENABLE_LINUXDVB if (!opt_dvb_adapters) { adapter_mask = ~0; } else { char *p, *e; char *r = NULL; char *dvb_adapters = strdup(opt_dvb_adapters); adapter_mask = 0x0; p = strtok_r(dvb_adapters, ",", &r); while (p) { int a = strtol(p, &e, 10); if (*e != 0 || a < 0 || a > 31) { fprintf(stderr, _("Invalid adapter number '%s'\n"), p); free(dvb_adapters); return 1; } adapter_mask |= (1 << a); p = strtok_r(NULL, ",", &r); } free(dvb_adapters); if (!adapter_mask) { fprintf(stderr, "%s", _("No adapters specified!\n")); return 1; } } #endif if (tvheadend_webroot) { char *tmp; if (*tvheadend_webroot == '/') tmp = strdup(tvheadend_webroot); else { tmp = malloc(strlen(tvheadend_webroot)+2); *tmp = '/'; strcpy(tmp+1, tvheadend_webroot); } if (tmp[strlen(tmp)-1] == '/') tmp[strlen(tmp)-1] = '\0'; tvheadend_webroot = tmp; } tvheadend_webui_debug = opt_uidebug; /* Setup logging */ if (isatty(2)) log_options |= TVHLOG_OPT_DECORATE; if (opt_stderr || opt_syslog || opt_logpath) { if (!opt_log_trace && !opt_log_debug) log_debug = "all"; log_level = LOG_DEBUG; if (opt_stderr) log_options |= TVHLOG_OPT_DBG_STDERR; if (opt_syslog) log_options |= TVHLOG_OPT_DBG_SYSLOG; if (opt_logpath) log_options |= TVHLOG_OPT_DBG_FILE; } if (opt_nosyslog) log_options &= ~(TVHLOG_OPT_SYSLOG|TVHLOG_OPT_DBG_SYSLOG); if (opt_fileline) log_options |= TVHLOG_OPT_FILELINE; if (opt_threadid) log_options |= TVHLOG_OPT_THREAD; if (opt_libav) log_options |= TVHLOG_OPT_LIBAV; if (opt_log_trace) { log_level = LOG_TRACE; log_trace = opt_log_trace; } if (opt_log_debug) log_debug = opt_log_debug; tvhlog_init(log_level, log_options, opt_logpath); tvhlog_set_debug(log_debug); tvhlog_set_trace(log_trace); tvhinfo("main", "Log started"); signal(SIGPIPE, handle_sigpipe); // will be redundant later signal(SIGILL, handle_sigill); // see handler.. /* Set priviledges */ if(opt_fork || opt_group || opt_user) { const char *homedir; struct group *grp = getgrnam(opt_group ?: "video"); struct passwd *pw = opt_user ? getpwnam(opt_user) : NULL; if(grp != NULL) { gid = grp->gr_gid; } else { gid = 1; } if (pw != NULL) { if (getuid() != pw->pw_uid) { gid_t glist[16]; int gnum; gnum = get_user_groups(pw, glist, ARRAY_SIZE(glist)); if (gnum > 0 && setgroups(gnum, glist)) { char buf[256] = ""; int i; for (i = 0; i < gnum; i++) snprintf(buf + strlen(buf), sizeof(buf) - 1 - strlen(buf), ",%d", glist[i]); tvhlog(LOG_ALERT, "START", "setgroups(%s) failed, do you have permission?", buf+1); return 1; } } uid = pw->pw_uid; homedir = pw->pw_dir; setenv("HOME", homedir, 1); } else { uid = 1; } } uuid_init(); config_boot(opt_config, gid, uid); tcp_server_preinit(opt_ipv6); http_server_init(opt_bindaddr); // bind to ports only htsp_init(opt_bindaddr); // bind to ports only satip_server_init(opt_satip_rtsp); // bind to ports only if (opt_fork) pidfile = tvh_fopen(opt_pidpath, "w+"); if (gid != -1 && (getgid() != gid) && setgid(gid)) { tvhlog(LOG_ALERT, "START", "setgid(%d) failed, do you have permission?", gid); return 1; } if (uid != -1 && (getuid() != uid) && setuid(uid)) { tvhlog(LOG_ALERT, "START", "setuid(%d) failed, do you have permission?", uid); return 1; } /* Daemonise */ if(opt_fork) { if(daemon(0, 0)) { exit(2); } if(pidfile != NULL) { fprintf(pidfile, "%d\n", getpid()); fclose(pidfile); } /* Make dumpable */ if (opt_dump) { #ifdef PLATFORM_LINUX if (chdir("/tmp")) tvhwarn("START", "failed to change cwd to /tmp"); prctl(PR_SET_DUMPABLE, 1); #else tvhwarn("START", "Coredumps not implemented on your platform"); #endif } umask(0); } tvheadend_running = 1; /* Start log thread (must be done post fork) */ tvhlog_start(); /* Alter logging */ if (opt_fork) tvhlog_options &= ~TVHLOG_OPT_STDERR; if (!isatty(2)) tvhlog_options &= ~TVHLOG_OPT_DECORATE; /* Initialise clock */ pthread_mutex_lock(&global_lock); time(&dispatch_clock); /* Signal handling */ sigfillset(&set); sigprocmask(SIG_BLOCK, &set, NULL); trap_init(argv[0]); /* SSL library init */ OPENSSL_config(NULL); SSL_load_error_strings(); SSL_library_init(); /* Initialise configuration */ notify_init(); idnode_init(); spawn_init(); config_init(opt_nobackup == 0); /** * Initialize subsystems */ epg_in_load = 1; tvhthread_create(&tasklet_tid, NULL, tasklet_thread, NULL); dbus_server_init(opt_dbus, opt_dbus_session); intlconv_init(); api_init(); fsmonitor_init(); libav_init(); tvhtime_init(); profile_init(); imagecache_init(); http_client_init(opt_user_agent); esfilter_init(); bouquet_init(); service_init(); dvb_init(); #if ENABLE_MPEGTS mpegts_init(adapter_mask, &opt_satip_xml, &opt_tsfile, opt_tsfile_tuner); #endif channel_init(); bouquet_service_resolve(); subscription_init(); dvr_config_init(); access_init(opt_firstrun, opt_noacl); #if ENABLE_TIMESHIFT timeshift_init(); #endif tcp_server_init(); webui_init(opt_xspf); #if ENABLE_UPNP upnp_server_init(opt_bindaddr); #endif service_mapper_init(); descrambler_init(); epggrab_init(); epg_init(); dvr_init(); dbus_server_start(); http_server_register(); satip_server_register(); htsp_register(); if(opt_subscribe != NULL) subscription_dummy_join(opt_subscribe, 1); avahi_init(); bonjour_init(); epg_updated(); // cleanup now all prev ref's should have been created epg_in_load = 0; pthread_mutex_unlock(&global_lock); /** * Wait for SIGTERM / SIGINT, but only in this thread */ sigemptyset(&set); sigaddset(&set, SIGTERM); sigaddset(&set, SIGINT); signal(SIGTERM, doexit); signal(SIGINT, doexit); pthread_sigmask(SIG_UNBLOCK, &set, NULL); tvhlog(LOG_NOTICE, "START", "HTS Tvheadend version %s started, " "running as PID:%d UID:%d GID:%d, CWD:%s CNF:%s", tvheadend_version, getpid(), getuid(), getgid(), getcwd(buf, sizeof(buf)), hts_settings_get_root()); if(opt_abort) abort(); mainloop(); #if ENABLE_DBUS_1 tvhftrace("main", dbus_server_done); #endif #if ENABLE_UPNP tvhftrace("main", upnp_server_done); #endif tvhftrace("main", satip_server_done); tvhftrace("main", htsp_done); tvhftrace("main", http_server_done); tvhftrace("main", webui_done); tvhftrace("main", fsmonitor_done); tvhftrace("main", http_client_done); tvhftrace("main", tcp_server_done); // Note: the locking is obviously a bit redundant, but without // we need to disable the gtimer_arm call in epg_save() pthread_mutex_lock(&global_lock); tvhftrace("main", epg_save); #if ENABLE_TIMESHIFT tvhftrace("main", timeshift_term); #endif pthread_mutex_unlock(&global_lock); tvhftrace("main", epggrab_done); #if ENABLE_MPEGTS tvhftrace("main", mpegts_done); #endif tvhftrace("main", descrambler_done); tvhftrace("main", service_mapper_done); tvhftrace("main", service_done); tvhftrace("main", channel_done); tvhftrace("main", bouquet_done); tvhftrace("main", dvr_done); tvhftrace("main", subscription_done); tvhftrace("main", access_done); tvhftrace("main", epg_done); tvhftrace("main", avahi_done); tvhftrace("main", bonjour_done); tvhftrace("main", imagecache_done); tvhftrace("main", lang_code_done); tvhftrace("main", api_done); tvhtrace("main", "tasklet enter"); pthread_cond_signal(&tasklet_cond); pthread_join(tasklet_tid, NULL); tvhtrace("main", "tasklet thread end"); tasklet_flush(); tvhtrace("main", "tasklet leave"); tvhftrace("main", hts_settings_done); tvhftrace("main", dvb_done); tvhftrace("main", lang_str_done); tvhftrace("main", esfilter_done); tvhftrace("main", profile_done); tvhftrace("main", intlconv_done); tvhftrace("main", urlparse_done); tvhftrace("main", idnode_done); tvhftrace("main", notify_done); tvhftrace("main", spawn_done); tvhlog(LOG_NOTICE, "STOP", "Exiting HTS Tvheadend"); tvhlog_end(); tvhftrace("main", config_done); if(opt_fork) unlink(opt_pidpath); #if ENABLE_TSFILE free(opt_tsfile.str); #endif free(opt_satip_xml.str); /* OpenSSL - welcome to the "cleanup" hell */ ENGINE_cleanup(); RAND_cleanup(); CRYPTO_cleanup_all_ex_data(); EVP_cleanup(); CONF_modules_free(); #ifndef OPENSSL_NO_COMP COMP_zlib_cleanup(); #endif ERR_remove_state(0); ERR_free_strings(); #ifndef OPENSSL_NO_COMP sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); #endif /* end of OpenSSL cleanup code */ #if ENABLE_DBUS_1 extern void dbus_shutdown(void); if (opt_dbus) dbus_shutdown(); #endif tvh_gettext_done(); return 0; } /** * */ void tvh_str_set(char **strp, const char *src) { free(*strp); *strp = src ? strdup(src) : NULL; } /** * */ int tvh_str_update(char **strp, const char *src) { if(src == NULL) return 0; free(*strp); *strp = strdup(src); return 1; } /** * */ void scopedunlock(pthread_mutex_t **mtxp) { pthread_mutex_unlock(*mtxp); }
void requestInit() override { handlers.reset(); // restore the old signal mask, thus unblock those that should be pthread_sigmask(SIG_SETMASK, &oldSet, NULL); inited.store(true); }
static void unblock_atimers (sigset_t const *oldset) { pthread_sigmask (SIG_SETMASK, oldset, 0); }
pid_t qemu_fork(Error **errp) { sigset_t oldmask, newmask; struct sigaction sig_action; int saved_errno; pid_t pid; /* * Need to block signals now, so that child process can safely * kill off caller's signal handlers without a race. */ sigfillset(&newmask); if (pthread_sigmask(SIG_SETMASK, &newmask, &oldmask) != 0) { error_setg_errno(errp, errno, "cannot block signals"); return -1; } pid = fork(); saved_errno = errno; if (pid < 0) { /* attempt to restore signal mask, but ignore failure, to * avoid obscuring the fork failure */ (void)pthread_sigmask(SIG_SETMASK, &oldmask, NULL); error_setg_errno(errp, saved_errno, "cannot fork child process"); errno = saved_errno; return -1; } else if (pid) { /* parent process */ /* Restore our original signal mask now that the child is * safely running. Only documented failures are EFAULT (not * possible, since we are using just-grabbed mask) or EINVAL * (not possible, since we are using correct arguments). */ (void)pthread_sigmask(SIG_SETMASK, &oldmask, NULL); } else { /* child process */ size_t i; /* Clear out all signal handlers from parent so nothing * unexpected can happen in our child once we unblock * signals */ sig_action.sa_handler = SIG_DFL; sig_action.sa_flags = 0; sigemptyset(&sig_action.sa_mask); for (i = 1; i < NSIG; i++) { /* Only possible errors are EFAULT or EINVAL The former * won't happen, the latter we expect, so no need to check * return value */ (void)sigaction(i, &sig_action, NULL); } /* Unmask all signals in child, since we've no idea what the * caller's done with their signal mask and don't want to * propagate that to children */ sigemptyset(&newmask); if (pthread_sigmask(SIG_SETMASK, &newmask, NULL) != 0) { Error *local_err = NULL; error_setg_errno(&local_err, errno, "cannot unblock signals"); error_report_err(local_err); _exit(1); } } return pid; }
LW_NTSTATUS LwRtlMain( VOID ) { NTSTATUS status = STATUS_SUCCESS; sigset_t waitSet; sigset_t intSet; siginfo_t info = {0}; struct sigaction action; int ret = 0; int i = 0; memset(&action, 0, sizeof(action)); LOCK_SIGNAL(); sigfillset(&waitSet); sigfillset(&intSet); sigdelset(&intSet, SIGINT); for (i = 0; SignalBlacklist[i]; i++) { sigdelset(&waitSet, SignalBlacklist[i]); sigdelset(&intSet, SignalBlacklist[i]); } /* Set a special handler for SIGINT */ action.sa_handler = InterruptHandler; action.sa_flags = 0; if (sigaction(SIGINT, &action, NULL) < 0) { status = LwErrnoToNtStatus(errno); GOTO_ERROR_ON_STATUS(status); } status = LwRtlBlockSignals(); GOTO_ERROR_ON_STATUS(status); for (;;) { UNLOCK_SIGNAL(); // sigwaitinfo on HPUX 11.11 does not fill-in info.si_signo. #if defined(HAVE_SIGWAITINFO) && !defined(__LWI_HP_UX__) ret = sigwaitinfo(&waitSet, &info); #else ret = sigwait(&waitSet, &info.si_signo); #endif LOCK_SIGNAL(); if (ret < 0 && errno == EINTR) { continue; } if (ret < 0) { status = LwErrnoToNtStatus(errno); GOTO_ERROR_ON_STATUS(status); } if (gSignal.bExit) { status = gSignal.Status; gSignal.bExit = FALSE; gSignal.Status = STATUS_SUCCESS; break; } if (info.si_signo == SIGINT) { /* Make hitting ^C to break into a process in gdb work. * * gdb can't trap SIGINT when we receive it with sigwaitinfo(), * so we reraise it against the process and then unblock it to * give the debugger a chance to intercept it. If it is not * intercepted, InterruptHandler() will run and set gRealSigInt, * and we will forward the original SIGINT to all subscribed * tasks. If the signal is intercepted, we pretend the original * SIGINT never happened, and the desired debugging behavior * is preserved. */ gRealSigInt = FALSE; kill(getpid(), SIGINT); status = LwErrnoToNtStatus(pthread_sigmask(SIG_SETMASK, &intSet, NULL)); GOTO_ERROR_ON_STATUS(status); status = LwRtlBlockSignals(); GOTO_ERROR_ON_STATUS(status); if (!gRealSigInt) { continue; } } DispatchSignal(&info); } error: UNLOCK_SIGNAL(); return status; }
static void s_serviceSetHBSig( void ) { #if defined( HB_OS_UNIX ) || defined( HB_OS_OS2_GCC ) struct sigaction act; #if defined( HB_THREAD_SUPPORT ) && ! defined( HB_OS_OS2 ) sigset_t blockall; /* set signal mask */ sigemptyset( &blockall ); sigaddset( &blockall, SIGHUP ); sigaddset( &blockall, SIGQUIT ); sigaddset( &blockall, SIGILL ); sigaddset( &blockall, SIGABRT ); sigaddset( &blockall, SIGFPE ); sigaddset( &blockall, SIGSEGV ); sigaddset( &blockall, SIGTERM ); sigaddset( &blockall, SIGUSR1 ); sigaddset( &blockall, SIGUSR2 ); sigaddset( &blockall, SIGHUP ); pthread_sigmask( SIG_SETMASK, &blockall, NULL ); #endif /* to avoid problems with differ sigaction structures and uninitialized fields */ memset( &act, 0, sizeof( struct sigaction ) ); #if defined( HB_OS_OS2_GCC ) || defined( __WATCOMC__ ) act.sa_handler = s_signalHandler; #else /* using more descriptive sa_action instead of sa_handler */ act.sa_handler = NULL; /* if act.sa.. is a union, we just clean this */ act.sa_sigaction = s_signalHandler; /* this is what matters */ /* block al signals, we don't want to be interrupted. */ /*sigfillset( &act.sa_mask );*/ #endif #ifdef HB_OS_OS2_GCC act.sa_flags = SA_NOCLDSTOP; #else act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; #endif sigaction( SIGHUP, &act, NULL ); sigaction( SIGQUIT, &act, NULL ); sigaction( SIGILL, &act, NULL ); sigaction( SIGABRT, &act, NULL ); sigaction( SIGFPE, &act, NULL ); sigaction( SIGSEGV, &act, NULL ); sigaction( SIGTERM, &act, NULL ); sigaction( SIGUSR1, &act, NULL ); sigaction( SIGUSR2, &act, NULL ); /* IGNORE pipe */ signal( SIGPIPE, SIG_IGN ); #endif #ifdef HB_OS_WIN /* disable all os-level error boxes */ s_uiErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX ); SetUnhandledExceptionFilter( s_exceptionFilter ); s_hMsgHook = SetWindowsHookEx( WH_GETMESSAGE, ( HOOKPROC ) s_MsgFilterFunc, NULL, GetCurrentThreadId() ); SetConsoleCtrlHandler( s_ConsoleHandlerRoutine, TRUE ); #endif }
static void * s_signalListener( void * my_stack ) { static HB_BOOL bFirst = HB_TRUE; sigset_t passall; HB_STACK * pStack = ( HB_STACK * ) my_stack; #if defined( HB_OS_BSD ) int sig; #else siginfo_t sinfo; #endif #ifdef HB_THREAD_TLS_KEYWORD hb_thread_stack = my_stack; #else pthread_setspecific( hb_pkCurrentStack, my_stack ); #endif pStack->th_id = HB_CURRENT_THREAD(); hb_threadLinkStack( pStack ); HB_STACK_LOCK; /* and now accepts all signals */ sigemptyset( &passall ); /* and wait for all signals */ sigaddset( &passall, SIGHUP ); sigaddset( &passall, SIGQUIT ); sigaddset( &passall, SIGILL ); sigaddset( &passall, SIGABRT ); sigaddset( &passall, SIGFPE ); sigaddset( &passall, SIGSEGV ); sigaddset( &passall, SIGTERM ); sigaddset( &passall, SIGUSR1 ); sigaddset( &passall, SIGUSR2 ); sigaddset( &passall, SIGHUP ); pthread_cleanup_push( hb_threadTerminator, my_stack ); pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, NULL ); pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL ); for(;; ) { /* allow safe cancelation */ HB_STACK_UNLOCK; /* reset signal handling; this is done here (so I don't mangle with pthread_ calls, and I don't hold mutexes), and just once (doing it twice would be useless). */ if( bFirst ) { pthread_sigmask( SIG_SETMASK, &passall, NULL ); bFirst = HB_FALSE; } /* This is also a cancelation point. When the main thread is done, it will kill all the threads having a stack including this one. ATM we don't care very much about signal handling during termination: no handler is set for them, so the DFL action is taken (and that should be fine). */ #if defined( HB_OS_BSD ) sigwait( &passall, &sig ); #else sigwaitinfo( &passall, &sinfo ); #endif /* lock stack before passing the ball to VM. */ HB_STACK_LOCK; #if defined( HB_OS_BSD ) s_signalHandler( sig, NULL, NULL ); #else s_signalHandler( sinfo.si_signo, &sinfo, NULL ); #endif } pthread_cleanup_pop( 1 ); return 0; }
void * thread_main ( void *arg ) { int connfd = -1; int thread_nr = -1; int *arg_int = NULL; struct sigaction sa; PKI_X509_OCSP_REQ *req = NULL; PKI_X509_OCSP_RESP *resp = NULL; if (arg) { arg_int = (int *) arg; thread_nr = *arg_int; PKI_Free(arg); } else { thread_nr = -1; } if ( ocspd_conf->verbose ) PKI_log(PKI_LOG_INFO, "New Thread Started [%d]", thread_nr); // PThread specific SIGPIPE handling sigset_t sigpipe_mask; sigset_t saved_mask; // Let's initialize the sigpipe mask sigemptyset(&sigpipe_mask); // Let's add the SIGPIPE to the mask sigaddset(&sigpipe_mask, SIGPIPE); // Prevent the server to die in case of a write to a prematurely closed socket if (pthread_sigmask(SIG_BLOCK, &sigpipe_mask, &saved_mask) == -1) { PKI_log_err("Can not block SIGPIPE signal!"); exit(1); } for ( ; ; ) { /* Before calling the cond_wait we need to own the mutex */ PKI_MUTEX_acquire ( &ocspd_conf->mutexes[CLIFD_MUTEX] ); while(ocspd_conf->connfd <= 2) { PKI_COND_wait ( &ocspd_conf->condVars[CLIFD_COND], &ocspd_conf->mutexes[CLIFD_MUTEX] ); } // Let's copy the socket descriptor connfd = ocspd_conf->connfd; // Reset the global value ocspd_conf->connfd = -1; // Let's now release the mutex to allow for the server to listen // for the next connection PKI_MUTEX_release ( &ocspd_conf->mutexes[CLIFD_MUTEX] ); // Communicate to the main thread to listen for the next connection PKI_MUTEX_acquire ( &ocspd_conf->mutexes[SRVFD_MUTEX] ); PKI_COND_signal ( &ocspd_conf->condVars[SRVFD_COND] ); PKI_MUTEX_release ( &ocspd_conf->mutexes[SRVFD_MUTEX] ); // Retrieves the request from the socket req = ocspd_req_get_socket(connfd, ocspd_conf); // If there is an error and we want to debug, let's print some useful info if (req == NULL && ocspd_conf->debug) PKI_log_debug("Can not parse REQ"); // Now let's build the response resp = make_ocsp_response(req, ocspd_conf); // If we do not have a response, we were not able to generate one // from the received request, let's send a generic error. if (resp == NULL) { // Error info PKI_log_err("Can not generate the OCSP response (internal error)"); // Generate the error response resp = PKI_X509_OCSP_RESP_new(); if (resp != NULL) { PKI_X509_OCSP_RESP_set_status(resp, PKI_X509_OCSP_RESP_STATUS_MALFORMEDREQUEST ); } } end: // If we have a response, let's send it over the wire and free // the associated memory if (resp != NULL) { // Send the response over the wire ocspd_resp_send_socket( connfd, resp, ocspd_conf ); // Frees the response memory PKI_X509_OCSP_RESP_free (resp); } // Free the memory associated with the request if (req != NULL) PKI_X509_OCSP_REQ_free (req); // Finally close the current socket PKI_NET_close(connfd); } }
int main(int argc, char *argv[]) { char *myfile; int i, totalsize = 0; int max_cpus = sysconf(_SC_NPROCESSORS_CONF); int oldsamples = 1; key_t key; union semun args; struct params *receiver = NULL; struct params *sender = NULL; sigset_t sigset; void *param = NULL; char f_opt[8]; struct timespec launchdelay, maindelay; myfile = getenv("_"); if (myfile == NULL) myfile = argv[0]; process_options(argc, argv); if (check_privs()) return 1; if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) { perror("mlockall"); return 1; } get_cpu_setup(); if (mustfork) { int shmem; /* * In fork mode (-f), the shared memory contains two * subsequent arrays, receiver[num_threads] and * sender[num_threads]. */ totalsize = num_threads * sizeof(struct params) * 2; shm_unlink("/sigwaittest"); shmem = shm_open("/sigwaittest", O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); if (shmem < 0) { fprintf(stderr, "Could not create shared memory\n"); return 1; } ftruncate(shmem, totalsize); param = mmap(0, totalsize, PROT_READ|PROT_WRITE, MAP_SHARED, shmem, 0); if (param == MAP_FAILED) { fprintf(stderr, "Could not map shared memory\n"); close(shmem); return 1; } receiver = (struct params *) param; sender = receiver + num_threads; } else if (wasforked) { struct stat buf; int shmem, totalsize, expect_totalsize; if (wasforked_threadno == -1 || wasforked_sender == -1) { fprintf(stderr, "Invalid fork option\n"); return 1; } shmem = shm_open("/sigwaittest", O_RDWR, S_IRUSR|S_IWUSR); if (fstat(shmem, &buf)) { fprintf(stderr, "Could not determine shared memory size\n"); close(shmem); return 1; } totalsize = buf.st_size; param = mmap(0, totalsize, PROT_READ|PROT_WRITE, MAP_SHARED, shmem, 0); close(shmem); if (param == MAP_FAILED) { fprintf(stderr, "Could not map shared memory\n"); return 1; } receiver = (struct params *) param; expect_totalsize = receiver->num_threads * sizeof(struct params) * 2; if (totalsize != expect_totalsize) { fprintf(stderr, "Memory size problem (expected %d, " "found %d\n", expect_totalsize, totalsize); munmap(param, totalsize); return 1; } sender = receiver + receiver->num_threads; if (wasforked_sender) semathread(sender + wasforked_threadno); else semathread(receiver + wasforked_threadno); munmap(param, totalsize); return 0; } signal(SIGINT, sighand); signal(SIGTERM, sighand); sigemptyset(&sigset); pthread_sigmask(SIG_SETMASK, &sigset, NULL); if (!mustfork && !wasforked) { receiver = calloc(num_threads, sizeof(struct params)); sender = calloc(num_threads, sizeof(struct params)); if (receiver == NULL || sender == NULL) goto nomem; } launchdelay.tv_sec = 0; launchdelay.tv_nsec = 10000000; /* 10 ms */ maindelay.tv_sec = 0; maindelay.tv_nsec = 50000000; /* 50 ms */ for (i = 0; i < num_threads; i++) { struct sembuf sb = { 0, 0, 0}; receiver[i].mindiff = UINT_MAX; receiver[i].maxdiff = 0; receiver[i].sumdiff = 0.0; if ((key = ftok(myfile, i)) == -1) { perror("ftok"); goto nosem; } if ((receiver[i].semid = semget(key, 2, 0666 | IPC_CREAT)) == -1) { perror("semget"); goto nosem; } args.val = 1; if (semctl(receiver[i].semid, SEM_WAIT_FOR_RECEIVER, SETVAL, args) == -1) { perror("semctl sema #0"); goto nosem; } if (semctl(receiver[i].semid, SEM_WAIT_FOR_SENDER, SETVAL, args) == -1) { perror("semctl sema #1"); goto nosem; } sb.sem_num = SEM_WAIT_FOR_RECEIVER; sb.sem_op = SEM_LOCK; semop(receiver[i].semid, &sb, 1); sb.sem_num = SEM_WAIT_FOR_SENDER; sb.sem_op = SEM_LOCK; semop(receiver[i].semid, &sb, 1); receiver[i].cpu = i; switch (setaffinity) { case AFFINITY_UNSPECIFIED: receiver[i].cpu = -1; break; case AFFINITY_SPECIFIED: receiver[i].cpu = affinity; break; case AFFINITY_USEALL: receiver[i].cpu = i % max_cpus; break; } receiver[i].priority = priority; receiver[i].tracelimit = tracelimit; if (priority > 1 && !sameprio) priority--; receiver[i].delay.tv_sec = interval / USEC_PER_SEC; receiver[i].delay.tv_nsec = (interval % USEC_PER_SEC) * 1000; interval += distance; receiver[i].max_cycles = max_cycles; receiver[i].sender = 0; receiver[i].neighbor = &sender[i]; if (mustfork) { pid_t pid = fork(); if (pid == -1) { fprintf(stderr, "Could not fork\n"); return 1; } else if (pid == 0) { char *args[3]; receiver[i].num_threads = num_threads; receiver[i].pid = getpid(); sprintf(f_opt, "-fr%d", i); args[0] = argv[0]; args[1] = f_opt; args[2] = NULL; execvp(args[0], args); fprintf(stderr, "Could not execute receiver child process " "#%d\n", i); } } else pthread_create(&receiver[i].threadid, NULL, semathread, &receiver[i]); nanosleep(&launchdelay, NULL); memcpy(&sender[i], &receiver[i], sizeof(receiver[0])); sender[i].sender = 1; sender[i].neighbor = &receiver[i]; if (mustfork) { pid_t pid = fork(); if (pid == -1) { fprintf(stderr, "Could not fork\n"); return 1; } else if (pid == 0) { char *args[3]; sender[i].num_threads = num_threads; sender[i].pid = getpid(); sprintf(f_opt, "-fs%d", i); args[0] = argv[0]; args[1] = f_opt; args[2] = NULL; execvp(args[0], args); fprintf(stderr, "Could not execute sender child process " "#%d\n", i); } } else pthread_create(&sender[i].threadid, NULL, semathread, &sender[i]); } while (!mustshutdown) { int printed; int errorlines = 0; for (i = 0; i < num_threads; i++) mustshutdown |= receiver[i].shutdown | sender[i].shutdown; if (receiver[0].samples > oldsamples || mustshutdown) { for (i = 0; i < num_threads; i++) { int receiver_pid, sender_pid; if (mustfork) { receiver_pid = receiver[i].pid; sender_pid = sender[i].pid; } else { receiver_pid = receiver[i].tid; sender_pid = sender[i].tid; } printf("#%1d: ID%d, P%d, CPU%d, I%ld; #%1d: " "ID%d, P%d, CPU%d, Cycles %d\n", i*2, receiver_pid, receiver[i].priority, receiver[i].cpu, receiver[i].delay.tv_nsec / 1000, i*2+1, sender_pid, sender[i].priority, sender[i].cpu, sender[i].samples); } for (i = 0; i < num_threads; i++) { if (receiver[i].mindiff == -1) printf("#%d -> #%d (not yet ready)\n", i*2+1, i*2); else printf("#%d -> #%d, Min %4d, Cur %4d, " "Avg %4d, Max %4d\n", i*2+1, i*2, receiver[i].mindiff, (int) receiver[i].diff.tv_usec, (int) ((receiver[i].sumdiff / receiver[i].samples) + 0.5), receiver[i].maxdiff); if (receiver[i].error[0] != '\0') { printf(receiver[i].error); receiver[i].error[0] = '\0'; errorlines++; } if (sender[i].error[0] != '\0') { printf(sender[i].error); sender[i].error[0] = '\0'; errorlines++; } } printed = 1; } else printed = 0; sigemptyset(&sigset); sigaddset(&sigset, SIGTERM); sigaddset(&sigset, SIGINT); pthread_sigmask(SIG_SETMASK, &sigset, NULL); nanosleep(&maindelay, NULL); sigemptyset(&sigset); pthread_sigmask(SIG_SETMASK, &sigset, NULL); if (printed && !mustshutdown) printf("\033[%dA", num_threads*2 + errorlines); } for (i = 0; i < num_threads; i++) { receiver[i].shutdown = 1; sender[i].shutdown = 1; } nanosleep(&receiver[0].delay, NULL); for (i = 0; i < num_threads; i++) { if (!receiver[i].stopped) { if (mustfork) kill(receiver[i].pid, SIGTERM); else pthread_kill(receiver[i].threadid, SIGTERM); } if (!sender[i].stopped) { if (mustfork) kill(sender[i].pid, SIGTERM); else pthread_kill(sender[i].threadid, SIGTERM); } } nosem: for (i = 0; i < num_threads; i++) semctl(receiver[i].semid, -1, IPC_RMID); nomem: if (mustfork) { munmap(param, totalsize); shm_unlink("/sigwaittest"); } return 0; }
void netsys_not_event_signal(struct not_event *ne) { #ifndef HAVE_GCC_COMPARE_AND_SWAP #ifdef HAVE_POSIX_SIGNALS sigset_t set, oldset; #endif #endif #ifdef HAVE_POLL switch (ne->type) { case NE_PIPE: #ifdef HAVE_GCC_COMPARE_AND_SWAP /* The elegant solution. See http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html for documentation */ if (__sync_bool_compare_and_swap(&(ne->state), 0, 1)) { if (ne->fd2 >= 0) { int n; n = write(ne->fd2, "X", 1); if (n == -1) { fprintf(stderr, "Cannot write to signaling pipe [netsys_c_event.c]\n"); } } } #else /* We have to protect against concurrent calls of this functions from signal handlers and from other threads. First, we block signals for this thread. Once we did this, the only other reason for running this can be another thread calling this function. The second measure is to use a mutex to block the other thread temporarily. NB If called from a signal handler, and if we use a pipe, this function is not absolutely correct. Actually, we are not allowed to call pthread_mutex_lock. It's not async-signal-safe. - TO BE SOLVED */ #ifdef HAVE_POSIX_SIGNALS sigfillset(&set); #ifdef HAVE_PTHREAD pthread_sigmask(SIG_BLOCK, &set, &oldset); #else sigprocmask(SIG_BLOCK, &set, &oldset); #endif /* HAVE_PTHREAD */ #endif /* HAVE_POSIX_SIGNALS */ #ifdef HAVE_PTHREAD pthread_mutex_lock(&(ne->mutex)); #endif /* HAVE_PTHREAD */ if (ne->state == 0) { ne->state = 1; if (ne->fd2 >= 0) write(ne->fd2, "X", 1); } #ifdef HAVE_PTHREAD pthread_mutex_unlock(&(ne->mutex)); #endif /* HAVE_PTHREAD */ #ifdef HAVE_POSIX_SIGNALS #ifdef HAVE_PTHREAD pthread_sigmask(SIG_SETMASK, &oldset, NULL); #else sigprocmask(SIG_SETMASK, &oldset, NULL); #endif /* HAVE_PTHREAD */ #endif /* HAVE_POSIX_SIGNALS */ #endif /* HAVE_GCC_COMPARE_AND_SWAP */ break; case NE_EVENTFD: { int64_t buf; buf = 1; if (ne->fd1 >= 0) { int n; n = write(ne->fd1, (char *) &buf, 8); if (n == -1) { fprintf(stderr, "Cannot write to signaling pipe [netsys_c_event.c]\n"); } }; break; } case NE_TIMERFD: /* not supported */ break; } #endif /* HAVE_POLL */ }
void *semathread(void *param) { int mustgetcpu = 0; struct params *par = param; cpu_set_t mask; int policy = SCHED_FIFO; struct sched_param schedp; struct sembuf sb = { 0, 0, 0}; sigset_t sigset; sigemptyset(&sigset); pthread_sigmask(SIG_SETMASK, &sigset, NULL); memset(&schedp, 0, sizeof(schedp)); schedp.sched_priority = par->priority; sched_setscheduler(0, policy, &schedp); if (par->cpu != -1) { CPU_ZERO(&mask); CPU_SET(par->cpu, &mask); if(sched_setaffinity(0, sizeof(mask), &mask) == -1) snprintf(par->error, sizeof(par->error), "WARNING: Could not set CPU affinity " "to CPU #%d\n", par->cpu); } else { int max_cpus = sysconf(_SC_NPROCESSORS_CONF); if (max_cpus > 1) mustgetcpu = 1; else par->cpu = 0; } if (!wasforked) par->tid = gettid(); while (!par->shutdown) { if (par->sender) { sb.sem_num = SEM_WAIT_FOR_SENDER; sb.sem_op = SEM_UNLOCK; /* * Unlocking the semaphore: * Start of latency measurement ... */ gettimeofday(&par->unblocked, NULL); semop(par->semid, &sb, 1); par->samples++; if(par->max_cycles && par->samples >= par->max_cycles) par->shutdown = 1; if (mustgetcpu) par->cpu = get_cpu(); sb.sem_num = SEM_WAIT_FOR_RECEIVER; sb.sem_op = SEM_LOCK; semop(par->semid, &sb, 1); sb.sem_num = SEM_WAIT_FOR_SENDER; sb.sem_op = SEM_LOCK; semop(par->semid, &sb, 1); } else { /* Receiver */ struct params *neighbor; if (wasforked) neighbor = par + par->num_threads; else neighbor = par->neighbor; sb.sem_num = SEM_WAIT_FOR_SENDER; sb.sem_op = SEM_LOCK; semop(par->semid, &sb, 1); /* * ... We got the lock: * End of latency measurement */ gettimeofday(&par->received, NULL); par->samples++; if (par->max_cycles && par->samples >= par->max_cycles) par->shutdown = 1; if (mustgetcpu) par->cpu = get_cpu(); timersub(&par->received, &neighbor->unblocked, &par->diff); if (par->diff.tv_usec < par->mindiff) par->mindiff = par->diff.tv_usec; if (par->diff.tv_usec > par->maxdiff) par->maxdiff = par->diff.tv_usec; par->sumdiff += (double) par->diff.tv_usec; if (par->tracelimit && par->maxdiff > par->tracelimit) { char tracing_enabled_file[MAX_PATH]; strcpy(tracing_enabled_file, get_debugfileprefix()); strcat(tracing_enabled_file, "tracing_enabled"); int tracing_enabled = open(tracing_enabled_file, O_WRONLY); if (tracing_enabled >= 0) { write(tracing_enabled, "0", 1); close(tracing_enabled); } else snprintf(par->error, sizeof(par->error), "Could not access %s\n", tracing_enabled_file); par->shutdown = 1; neighbor->shutdown = 1; } sb.sem_num = SEM_WAIT_FOR_RECEIVER; sb.sem_op = SEM_UNLOCK; semop(par->semid, &sb, 1); nanosleep(&par->delay, NULL); sb.sem_num = SEM_WAIT_FOR_SENDER; sb.sem_op = SEM_UNLOCK; semop(par->semid, &sb, 1); } } if (par->sender) { sb.sem_num = SEM_WAIT_FOR_SENDER; sb.sem_op = SEM_UNLOCK; semop(par->semid, &sb, 1); sb.sem_num = SEM_WAIT_FOR_RECEIVER; sb.sem_op = SEM_UNLOCK; semop(par->semid, &sb, 1); } par->stopped = 1; return NULL; }
int main(int argc, char **argv) { int option; char *configfile; int background; int mdns_no_rsp; int mdns_no_daap; int mdns_no_mpd; int loglevel; char *logdomains; char *logfile; char *ffid; char *pidfile; const char *gcry_version; sigset_t sigs; int sigfd; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) struct kevent ke_sigs[4]; #endif int ret; struct option option_map[] = { { "ffid", 1, NULL, 'b' }, { "debug", 1, NULL, 'd' }, { "logdomains", 1, NULL, 'D' }, { "foreground", 0, NULL, 'f' }, { "config", 1, NULL, 'c' }, { "pidfile", 1, NULL, 'P' }, { "version", 0, NULL, 'v' }, { "mdns-no-rsp", 0, NULL, 512 }, { "mdns-no-daap", 0, NULL, 513 }, { NULL, 0, NULL, 0 } }; configfile = CONFFILE; pidfile = PIDFILE; loglevel = -1; logdomains = NULL; logfile = NULL; background = 1; ffid = NULL; mdns_no_rsp = 0; mdns_no_daap = 0; mdns_no_mpd = 1; // only announce if mpd protocol support is activated while ((option = getopt_long(argc, argv, "D:d:c:P:fb:v", option_map, NULL)) != -1) { switch (option) { case 512: mdns_no_rsp = 1; break; case 513: mdns_no_daap = 1; break; case 'b': ffid = optarg; break; case 'd': ret = safe_atoi32(optarg, &option); if (ret < 0) fprintf(stderr, "Error: loglevel must be an integer in '-d %s'\n", optarg); else loglevel = option; break; case 'D': logdomains = optarg; break; case 'f': background = 0; break; case 'c': configfile = optarg; break; case 'P': pidfile = optarg; break; case 'v': version(); return EXIT_SUCCESS; break; default: usage(argv[0]); return EXIT_FAILURE; break; } } ret = logger_init(NULL, NULL, (loglevel < 0) ? E_LOG : loglevel); if (ret != 0) { fprintf(stderr, "Could not initialize log facility\n"); return EXIT_FAILURE; } ret = conffile_load(configfile); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "Config file errors; please fix your config\n"); logger_deinit(); return EXIT_FAILURE; } logger_deinit(); /* Reinit log facility with configfile values */ if (loglevel < 0) loglevel = cfg_getint(cfg_getsec(cfg, "general"), "loglevel"); logfile = cfg_getstr(cfg_getsec(cfg, "general"), "logfile"); ret = logger_init(logfile, logdomains, loglevel); if (ret != 0) { fprintf(stderr, "Could not reinitialize log facility with config file settings\n"); conffile_unload(); return EXIT_FAILURE; } /* Set up libevent logging callback */ event_set_log_callback(logger_libevent); DPRINTF(E_LOG, L_MAIN, "Forked Media Server Version %s taking off\n", VERSION); ret = av_lockmgr_register(ffmpeg_lockmgr); if (ret < 0) { DPRINTF(E_FATAL, L_MAIN, "Could not register ffmpeg lock manager callback\n"); ret = EXIT_FAILURE; goto ffmpeg_init_fail; } av_register_all(); avfilter_register_all(); #if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 13) avformat_network_init(); #endif av_log_set_callback(logger_ffmpeg); #ifdef LASTFM /* Initialize libcurl */ curl_global_init(CURL_GLOBAL_DEFAULT); #endif /* Initialize libgcrypt */ gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); gcry_version = gcry_check_version(GCRYPT_VERSION); if (!gcry_version) { DPRINTF(E_FATAL, L_MAIN, "libgcrypt version mismatch\n"); ret = EXIT_FAILURE; goto gcrypt_init_fail; } /* We aren't handling anything sensitive, so give up on secure * memory, which is a scarce system resource. */ gcry_control(GCRYCTL_DISABLE_SECMEM, 0); gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); DPRINTF(E_DBG, L_MAIN, "Initialized with gcrypt %s\n", gcry_version); /* Block signals for all threads except the main one */ sigemptyset(&sigs); sigaddset(&sigs, SIGINT); sigaddset(&sigs, SIGHUP); sigaddset(&sigs, SIGCHLD); sigaddset(&sigs, SIGTERM); sigaddset(&sigs, SIGPIPE); ret = pthread_sigmask(SIG_BLOCK, &sigs, NULL); if (ret != 0) { DPRINTF(E_LOG, L_MAIN, "Error setting signal set\n"); ret = EXIT_FAILURE; goto signal_block_fail; } /* Daemonize and drop privileges */ ret = daemonize(background, pidfile); if (ret < 0) { DPRINTF(E_LOG, L_MAIN, "Could not initialize server\n"); ret = EXIT_FAILURE; goto daemon_fail; } /* Initialize event base (after forking) */ evbase_main = event_base_new(); DPRINTF(E_LOG, L_MAIN, "mDNS init\n"); ret = mdns_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "mDNS init failed\n"); ret = EXIT_FAILURE; goto mdns_fail; } /* Initialize the database before starting */ DPRINTF(E_INFO, L_MAIN, "Initializing database\n"); ret = db_init(); if (ret < 0) { DPRINTF(E_FATAL, L_MAIN, "Database init failed\n"); ret = EXIT_FAILURE; goto db_fail; } /* Open a DB connection for the main thread */ ret = db_perthread_init(); if (ret < 0) { DPRINTF(E_FATAL, L_MAIN, "Could not perform perthread DB init for main\n"); ret = EXIT_FAILURE; goto db_fail; } /* Spawn worker thread */ ret = worker_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "Worker thread failed to start\n"); ret = EXIT_FAILURE; goto worker_fail; } /* Spawn cache thread */ ret = cache_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "Cache thread failed to start\n"); ret = EXIT_FAILURE; goto cache_fail; } /* Spawn file scanner thread */ ret = filescanner_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "File scanner thread failed to start\n"); ret = EXIT_FAILURE; goto filescanner_fail; } #ifdef HAVE_SPOTIFY_H /* Spawn Spotify thread */ ret = spotify_init(); if (ret < 0) { DPRINTF(E_INFO, L_MAIN, "Spotify thread not started\n");; } #endif /* Spawn player thread */ ret = player_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "Player thread failed to start\n"); ret = EXIT_FAILURE; goto player_fail; } /* Spawn HTTPd thread */ ret = httpd_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "HTTPd thread failed to start\n"); ret = EXIT_FAILURE; goto httpd_fail; } #ifdef MPD /* Spawn MPD thread */ ret = mpd_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "MPD thread failed to start\n"); ret = EXIT_FAILURE; goto mpd_fail; } mdns_no_mpd = 0; #endif /* Start Remote pairing service */ ret = remote_pairing_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "Remote pairing service failed to start\n"); ret = EXIT_FAILURE; goto remote_fail; } /* Register mDNS services */ ret = register_services(ffid, mdns_no_rsp, mdns_no_daap, mdns_no_mpd); if (ret < 0) { ret = EXIT_FAILURE; goto mdns_reg_fail; } #if defined(__linux__) /* Set up signal fd */ sigfd = signalfd(-1, &sigs, SFD_NONBLOCK | SFD_CLOEXEC); if (sigfd < 0) { DPRINTF(E_FATAL, L_MAIN, "Could not setup signalfd: %s\n", strerror(errno)); ret = EXIT_FAILURE; goto signalfd_fail; } sig_event = event_new(evbase_main, sigfd, EV_READ, signal_signalfd_cb, NULL); #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) sigfd = kqueue(); if (sigfd < 0) { DPRINTF(E_FATAL, L_MAIN, "Could not setup kqueue: %s\n", strerror(errno)); ret = EXIT_FAILURE; goto signalfd_fail; } EV_SET(&ke_sigs[0], SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); EV_SET(&ke_sigs[1], SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); EV_SET(&ke_sigs[2], SIGHUP, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); EV_SET(&ke_sigs[3], SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); ret = kevent(sigfd, ke_sigs, 4, NULL, 0, NULL); if (ret < 0) { DPRINTF(E_FATAL, L_MAIN, "Could not register signal events: %s\n", strerror(errno)); ret = EXIT_FAILURE; goto signalfd_fail; } sig_event = event_new(evbase_main, sigfd, EV_READ, signal_kqueue_cb, NULL); #endif if (!sig_event) { DPRINTF(E_FATAL, L_MAIN, "Could not create signal event\n"); ret = EXIT_FAILURE; goto sig_event_fail; } event_add(sig_event, NULL); /* Run the loop */ event_base_dispatch(evbase_main); DPRINTF(E_LOG, L_MAIN, "Stopping gracefully\n"); ret = EXIT_SUCCESS; /* * On a clean shutdown, bring mDNS down first to give a chance * to the clients to perform a clean shutdown on their end */ DPRINTF(E_LOG, L_MAIN, "mDNS deinit\n"); mdns_deinit(); sig_event_fail: signalfd_fail: mdns_reg_fail: DPRINTF(E_LOG, L_MAIN, "Remote pairing deinit\n"); remote_pairing_deinit(); remote_fail: #ifdef MPD DPRINTF(E_LOG, L_MAIN, "MPD deinit\n"); mpd_deinit(); mpd_fail: #endif DPRINTF(E_LOG, L_MAIN, "HTTPd deinit\n"); httpd_deinit(); httpd_fail: DPRINTF(E_LOG, L_MAIN, "Player deinit\n"); player_deinit(); player_fail: #ifdef HAVE_SPOTIFY_H DPRINTF(E_LOG, L_MAIN, "Spotify deinit\n"); spotify_deinit(); #endif DPRINTF(E_LOG, L_MAIN, "File scanner deinit\n"); filescanner_deinit(); filescanner_fail: DPRINTF(E_LOG, L_MAIN, "Cache deinit\n"); cache_deinit(); cache_fail: DPRINTF(E_LOG, L_MAIN, "Worker deinit\n"); worker_deinit(); worker_fail: DPRINTF(E_LOG, L_MAIN, "Database deinit\n"); db_perthread_deinit(); db_deinit(); db_fail: if (ret == EXIT_FAILURE) { DPRINTF(E_LOG, L_MAIN, "mDNS deinit\n"); mdns_deinit(); } mdns_fail: daemon_fail: if (background) { ret = seteuid(0); if (ret < 0) DPRINTF(E_LOG, L_MAIN, "seteuid() failed: %s\n", strerror(errno)); else { ret = unlink(pidfile); if (ret < 0) DPRINTF(E_LOG, L_MAIN, "Could not unlink PID file %s: %s\n", pidfile, strerror(errno)); } } signal_block_fail: gcrypt_init_fail: #ifdef LASTFM curl_global_cleanup(); #endif #if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 13) avformat_network_deinit(); #endif av_lockmgr_register(NULL); ffmpeg_init_fail: DPRINTF(E_LOG, L_MAIN, "Exiting.\n"); conffile_unload(); logger_deinit(); return ret; }
/** * Manually process the flags for the registered secondary handler to call it as if it had been evoked by the OS * in response to a signal, without re-raising it. */ int omrsig_handler(int sig, void *siginfo, void *uc) { int rc = OMRSIG_RC_ERROR; if (validSignalNum(sig, false)) { /* Only mask signals and lock while getting the handler slot. */ SIGLOCK(sigMutex); OMR_SigData handlerSlot = sigData[sig]; SIGUNLOCK(sigMutex); if (handlerIsFunction(&handlerSlot.secondaryAction)) { #if defined(POSIX_SIGNAL) #if defined(OSX) sigset_t oldMask = {0}; #else /* defined(OSX) */ sigset_t oldMask = {{0}}; #endif /* defined(OSX) */ sigset_t usedMask = handlerSlot.secondaryAction.sa_mask; sigaddset(&usedMask, sig); int ec = pthread_sigmask(SIG_BLOCK, &usedMask, &oldMask); /* SA_NODEFER - If set, sig will not be added to the process' signal mask on entry to the signal handler * unless it is included in sa_mask. Otherwise, sig will always be added to the process' signal mask on * entry to the signal handler. */ if ((0 == ec) && ((handlerSlot.secondaryAction.sa_flags & SA_NODEFER) #if (defined(AIXPPC) || defined(J9ZOS390)) /* Only AIX and zos respects that SA_RESETHAND behaves like SA_NODEFER by POSIX spec. */ || (handlerSlot.secondaryAction.sa_flags & SA_RESETHAND) #endif /* (defined(AIXPPC) || defined(J9ZOS390)) */ )) { #if defined(OSX) sigset_t mask = {0}; #else /* defined(OSX) */ sigset_t mask = {{0}}; #endif /* defined(OSX) */ sigemptyset(&mask); sigaddset(&mask, sig); ec = pthread_sigmask(SIG_UNBLOCK, &mask, NULL); } /* SA_RESETHAND - If set, the disposition of the signal will be reset to SIG_DFL and the SA_SIGINFO flag * will be cleared on entry to the signal handler. Does not work for SIGILL or SIGTRAP, silently. Also * behaves like SA_NODEFER according to POSIX standard, but AIX is the supported OS found to do this. */ if (0 == ec) { sighandler_t handler = SIG_DFL; sigaction_t action = (sigaction_t)SIG_DFL; int flags = handlerSlot.secondaryAction.sa_flags; if (flags & SA_SIGINFO) { action = handlerSlot.secondaryAction.sa_sigaction; } else { handler = handlerSlot.secondaryAction.sa_handler; } if (handlerSlot.secondaryAction.sa_flags & SA_RESETHAND) { handlerSlot.secondaryAction.sa_flags &= ~SA_SIGINFO; handlerSlot.secondaryAction.sa_handler = SIG_DFL; omrsig_sigaction_internal(sig, &handlerSlot.secondaryAction, NULL, false); } /* SA_SIGINFO - The signal handler takes three arguments, not one. In this case, sa_sigaction should be * used instead of sa_handler. * NOTE FOR NOW: null, DFL, and IGN check the sa_handler when registering it, not here */ if (flags & SA_SIGINFO) { action(sig, (siginfo_t *)siginfo, uc); } else { handler(sig); } ec = pthread_sigmask(SIG_SETMASK, &oldMask, NULL); } if (0 == ec) { rc = OMRSIG_RC_SIGNAL_HANDLED; } #else /* defined(POSIX_SIGNAL) */ handlerSlot.secondaryAction.sa_handler(sig); rc = OMRSIG_RC_SIGNAL_HANDLED; #endif /* defined(POSIX_SIGNAL) */ } else if (SIG_DFL == handlerSlot.secondaryAction.sa_handler){ rc = OMRSIG_RC_DEFAULT_ACTION_REQUIRED; } } return rc; }
int main(int ac, char **av) { fd_set rfds; void *ipc; struct sigaction sv; sigset_t sigs; int ret; /* Parse argv args and initialize default options */ afp_options_parse_cmdline(&obj, ac, av); if (!(obj.cmdlineflags & OPTION_DEBUG) && (daemonize(0, 0) != 0)) exit(EXITERR_SYS); /* Log SIGBUS/SIGSEGV SBT */ fault_setup(NULL); if (afp_config_parse(&obj, "afpd") != 0) afp_exit(EXITERR_CONF); /* Save the user's current umask */ obj.options.save_mask = umask(obj.options.umask); /* install child handler for asp and dsi. we do this before afp_goaway * as afp_goaway references stuff from here. * XXX: this should really be setup after the initial connections. */ if (!(server_children = server_child_alloc(obj.options.connections, CHILD_NFORKS))) { LOG(log_error, logtype_afpd, "main: server_child alloc: %s", strerror(errno) ); afp_exit(EXITERR_SYS); } sigemptyset(&sigs); pthread_sigmask(SIG_SETMASK, &sigs, NULL); memset(&sv, 0, sizeof(sv)); /* linux at least up to 2.4.22 send a SIGXFZ for vfat fs, even if the file is open with O_LARGEFILE ! */ #ifdef SIGXFSZ sv.sa_handler = SIG_IGN; sigemptyset( &sv.sa_mask ); if (sigaction(SIGXFSZ, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); afp_exit(EXITERR_SYS); } #endif sv.sa_handler = afp_goaway; /* handler for all sigs */ sigemptyset( &sv.sa_mask ); sigaddset(&sv.sa_mask, SIGALRM); sigaddset(&sv.sa_mask, SIGHUP); sigaddset(&sv.sa_mask, SIGTERM); sigaddset(&sv.sa_mask, SIGUSR1); sigaddset(&sv.sa_mask, SIGQUIT); sv.sa_flags = SA_RESTART; if ( sigaction( SIGCHLD, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); afp_exit(EXITERR_SYS); } sigemptyset( &sv.sa_mask ); sigaddset(&sv.sa_mask, SIGALRM); sigaddset(&sv.sa_mask, SIGTERM); sigaddset(&sv.sa_mask, SIGHUP); sigaddset(&sv.sa_mask, SIGCHLD); sigaddset(&sv.sa_mask, SIGQUIT); sv.sa_flags = SA_RESTART; if ( sigaction( SIGUSR1, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); afp_exit(EXITERR_SYS); } sigemptyset( &sv.sa_mask ); sigaddset(&sv.sa_mask, SIGALRM); sigaddset(&sv.sa_mask, SIGTERM); sigaddset(&sv.sa_mask, SIGUSR1); sigaddset(&sv.sa_mask, SIGCHLD); sigaddset(&sv.sa_mask, SIGQUIT); sv.sa_flags = SA_RESTART; if ( sigaction( SIGHUP, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); afp_exit(EXITERR_SYS); } sigemptyset( &sv.sa_mask ); sigaddset(&sv.sa_mask, SIGALRM); sigaddset(&sv.sa_mask, SIGHUP); sigaddset(&sv.sa_mask, SIGUSR1); sigaddset(&sv.sa_mask, SIGCHLD); sigaddset(&sv.sa_mask, SIGQUIT); sv.sa_flags = SA_RESTART; if ( sigaction( SIGTERM, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); afp_exit(EXITERR_SYS); } sigemptyset( &sv.sa_mask ); sigaddset(&sv.sa_mask, SIGALRM); sigaddset(&sv.sa_mask, SIGHUP); sigaddset(&sv.sa_mask, SIGUSR1); sigaddset(&sv.sa_mask, SIGCHLD); sigaddset(&sv.sa_mask, SIGTERM); sv.sa_flags = SA_RESTART; if (sigaction(SIGQUIT, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); afp_exit(EXITERR_SYS); } /* afp.conf: not in config file: lockfile, configfile * preference: command-line provides defaults. * config file over-writes defaults. * * we also need to make sure that killing afpd during startup * won't leave any lingering registered names around. */ sigemptyset(&sigs); sigaddset(&sigs, SIGALRM); sigaddset(&sigs, SIGHUP); sigaddset(&sigs, SIGUSR1); #if 0 /* don't block SIGTERM */ sigaddset(&sigs, SIGTERM); #endif sigaddset(&sigs, SIGCHLD); pthread_sigmask(SIG_BLOCK, &sigs, NULL); if (configinit(&obj) != 0) { LOG(log_error, logtype_afpd, "main: no servers configured"); afp_exit(EXITERR_CONF); } pthread_sigmask(SIG_UNBLOCK, &sigs, NULL); /* Initialize */ cnid_init(); /* watch atp, dsi sockets and ipc parent/child file descriptor. */ if (obj.options.flags & OPTION_KEEPSESSIONS) { LOG(log_note, logtype_afpd, "Activating continous service"); disasociated_ipc_fd = ipc_server_uds(_PATH_AFP_IPC); } fd_set_listening_sockets(&obj); /* set limits */ (void)setlimits(); afp_child_t *child; int recon_ipc_fd; pid_t pid; int saveerrno; /* wait for an appleshare connection. parent remains in the loop * while the children get handled by afp_over_{asp,dsi}. this is * currently vulnerable to a denial-of-service attack if a * connection is made without an actual login attempt being made * afterwards. establishing timeouts for logins is a possible * solution. */ while (1) { LOG(log_maxdebug, logtype_afpd, "main: polling %i fds", fdset_used); pthread_sigmask(SIG_UNBLOCK, &sigs, NULL); ret = poll(fdset, fdset_used, -1); pthread_sigmask(SIG_BLOCK, &sigs, NULL); saveerrno = errno; if (gotsigchld) { gotsigchld = 0; child_handler(); continue; } if (reloadconfig) { nologin++; auth_unload(); fd_reset_listening_sockets(&obj); LOG(log_info, logtype_afpd, "re-reading configuration file"); configfree(&obj, NULL); if (configinit(&obj) != 0) { LOG(log_error, logtype_afpd, "config re-read: no servers configured"); afp_exit(EXITERR_CONF); } fd_set_listening_sockets(&obj); nologin = 0; reloadconfig = 0; errno = saveerrno; continue; } if (ret == 0) continue; if (ret < 0) { if (errno == EINTR) continue; LOG(log_error, logtype_afpd, "main: can't wait for input: %s", strerror(errno)); break; } for (int i = 0; i < fdset_used; i++) { if (fdset[i].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)) { switch (polldata[i].fdtype) { case LISTEN_FD: if (child = dsi_start(&obj, (DSI *)polldata[i].data, server_children)) { /* Add IPC fd to select fd set */ fdset_add_fd(obj.options.connections + AFP_LISTENERS + FDSET_SAFETY, &fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fd, IPC_FD, child); } break; case IPC_FD: child = (afp_child_t *)polldata[i].data; LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->pid); if (ipc_server_read(server_children, child->ipc_fd) != 0) { fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fd); close(child->ipc_fd); child->ipc_fd = -1; if ((obj.options.flags & OPTION_KEEPSESSIONS) && child->disasociated) { LOG(log_note, logtype_afpd, "main: removing reattached child[%u]", child->pid); server_child_remove(server_children, CHILD_DSIFORK, child->pid); } } break; case DISASOCIATED_IPC_FD: LOG(log_debug, logtype_afpd, "main: IPC reconnect request"); if ((recon_ipc_fd = accept(disasociated_ipc_fd, NULL, NULL)) == -1) { LOG(log_error, logtype_afpd, "main: accept: %s", strerror(errno)); break; } if (readt(recon_ipc_fd, &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) { LOG(log_error, logtype_afpd, "main: readt: %s", strerror(errno)); close(recon_ipc_fd); break; } LOG(log_note, logtype_afpd, "main: IPC reconnect from pid [%u]", pid); if ((child = server_child_add(server_children, CHILD_DSIFORK, pid, recon_ipc_fd)) == NULL) { LOG(log_error, logtype_afpd, "main: server_child_add"); close(recon_ipc_fd); break; } child->disasociated = 1; fdset_add_fd(obj.options.connections + AFP_LISTENERS + FDSET_SAFETY, &fdset, &polldata, &fdset_used, &fdset_size, recon_ipc_fd, IPC_FD, child); break; default: LOG(log_debug, logtype_afpd, "main: IPC request for unknown type"); break; } /* switch */ } /* if */ } /* for (i)*/ } /* while (1) */ return 0; }
int main(int argc, char **argv) { extern char *optarg; extern int optopt; int i, c, signal; size_t opt_subbuf_size = 0; size_t opt_n_subbufs = 0; sigset_t signals; pthread_mutex_init(&processing_mutex, NULL); sigemptyset(&signals); sigaddset(&signals, SIGINT); sigaddset(&signals, SIGTERM); pthread_sigmask(SIG_BLOCK, &signals, NULL); while ((c = getopt(argc, argv, "b:n:")) != -1) { switch (c) { case 'b': opt_subbuf_size = (unsigned)atoi(optarg); if (!opt_subbuf_size) usage(); break; case 'n': opt_n_subbufs = (unsigned)atoi(optarg); if (!opt_n_subbufs) usage(); break; case '?': printf("Unknown option -%c\n", optopt); usage(); break; default: break; } } if ((opt_n_subbufs && !opt_subbuf_size) || (!opt_n_subbufs && opt_subbuf_size)) usage(); if (opt_n_subbufs && opt_n_subbufs) { subbuf_size = opt_subbuf_size; n_subbufs = opt_n_subbufs; } ncpus = sysconf(_SC_NPROCESSORS_ONLN); control_write(app_dirname, "subbuf_size", subbuf_size); control_write(app_dirname, "n_subbufs", n_subbufs); /* disable logging in case we exited badly in a previous run */ control_write(app_dirname, "enabled", 0); fprintf(stderr, "control_write: create\n"); control_write(app_dirname, "create", 1); if (open_app_files()) return -1; if (open_control_files(app_dirname, percpu_basename)) { close_app_files(); return -1; } if (create_percpu_threads()) { close_control_files(); close_app_files(); return -1; } control_write(app_dirname, "enabled", 1); printf("Creating channel with %lu sub-buffers of size %lu.\n", n_subbufs, subbuf_size); printf("Logging... Press Control-C to stop.\n"); sigemptyset(&signals); sigaddset(&signals, SIGINT); sigaddset(&signals, SIGTERM); while (sigwait(&signals, &signal) == 0) { switch(signal) { case SIGINT: case SIGTERM: control_write(app_dirname, "enabled", 0); kill_percpu_threads(ncpus); while(1) { pthread_mutex_lock(&processing_mutex); if (!processing) { pthread_mutex_unlock(&processing_mutex); break; } pthread_mutex_unlock(&processing_mutex); } for (i = 0; i < ncpus; i++) check_buffer(i); summarize(); close_control_files(); close_app_files(); control_write(app_dirname, "create", 0); exit(0); } } }
isc_result_t isc__app_ctxstart(isc_appctx_t *ctx0) { isc__appctx_t *ctx = (isc__appctx_t *)ctx0; isc_result_t result; int presult; sigset_t sset; char strbuf[ISC_STRERRORSIZE]; REQUIRE(VALID_APPCTX(ctx)); /* * Start an ISC library application. */ #ifdef NEED_PTHREAD_INIT /* * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this. */ presult = pthread_init(); if (presult != 0) { isc__strerror(presult, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() pthread_init: %s", strbuf); return (ISC_R_UNEXPECTED); } #endif #ifdef ISC_PLATFORM_USETHREADS #ifdef HAVE_LINUXTHREADS main_thread = pthread_self(); #endif /* HAVE_LINUXTHREADS */ result = isc_mutex_init(&ctx->readylock); if (result != ISC_R_SUCCESS) return (result); result = isc_condition_init(&ctx->ready); if (result != ISC_R_SUCCESS) goto cleanup_rlock; result = isc_mutex_init(&ctx->lock); if (result != ISC_R_SUCCESS) goto cleanup_rcond; #else /* ISC_PLATFORM_USETHREADS */ result = isc_mutex_init(&ctx->lock); if (result != ISC_R_SUCCESS) goto cleanup; #endif /* ISC_PLATFORM_USETHREADS */ ISC_LIST_INIT(ctx->on_run); ctx->shutdown_requested = ISC_FALSE; ctx->running = ISC_FALSE; ctx->want_shutdown = ISC_FALSE; ctx->want_reload = ISC_FALSE; ctx->blocked = ISC_FALSE; #ifndef HAVE_SIGWAIT /* * Install do-nothing handlers for SIGINT and SIGTERM. * * We install them now because BSDI 3.1 won't block * the default actions, regardless of what we do with * pthread_sigmask(). */ result = handle_signal(SIGINT, exit_action); if (result != ISC_R_SUCCESS) goto cleanup; result = handle_signal(SIGTERM, exit_action); if (result != ISC_R_SUCCESS) goto cleanup; #endif /* * Always ignore SIGPIPE. */ result = handle_signal(SIGPIPE, SIG_IGN); if (result != ISC_R_SUCCESS) goto cleanup; /* * On Solaris 2, delivery of a signal whose action is SIG_IGN * will not cause sigwait() to return. We may have inherited * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent * process (e.g, Solaris cron). Set an action of SIG_DFL to make * sure sigwait() works as expected. Only do this for SIGTERM and * SIGINT if we don't have sigwait(), since a different handler is * installed above. */ result = handle_signal(SIGHUP, SIG_DFL); if (result != ISC_R_SUCCESS) goto cleanup; #ifdef HAVE_SIGWAIT result = handle_signal(SIGTERM, SIG_DFL); if (result != ISC_R_SUCCESS) goto cleanup; result = handle_signal(SIGINT, SIG_DFL); if (result != ISC_R_SUCCESS) goto cleanup; #endif #ifdef ISC_PLATFORM_USETHREADS /* * Block SIGHUP, SIGINT, SIGTERM. * * If isc_app_start() is called from the main thread before any other * threads have been created, then the pthread_sigmask() call below * will result in all threads having SIGHUP, SIGINT and SIGTERM * blocked by default, ensuring that only the thread that calls * sigwait() for them will get those signals. */ if (sigemptyset(&sset) != 0 || sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() sigsetops: %s", strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } presult = pthread_sigmask(SIG_BLOCK, &sset, NULL); if (presult != 0) { isc__strerror(presult, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() pthread_sigmask: %s", strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } #else /* ISC_PLATFORM_USETHREADS */ /* * Unblock SIGHUP, SIGINT, SIGTERM. * * If we're not using threads, we need to make sure that SIGHUP, * SIGINT and SIGTERM are not inherited as blocked from the parent * process. */ if (sigemptyset(&sset) != 0 || sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() sigsetops: %s", strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } presult = sigprocmask(SIG_UNBLOCK, &sset, NULL); if (presult != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() sigprocmask: %s", strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } #endif /* ISC_PLATFORM_USETHREADS */ return (ISC_R_SUCCESS); cleanup: #ifdef ISC_PLATFORM_USETHREADS cleanup_rcond: (void)isc_condition_destroy(&ctx->ready); cleanup_rlock: (void)isc_mutex_destroy(&ctx->readylock); #endif /* ISC_PLATFORM_USETHREADS */ return (result); }
void HttpServer::timeout_action() { string json_str = "{\"OK\":1}"; if (!m_server_checked) { // start widget again in case it dead. browser not need to restart g_error_code = 1; } else if (!m_test_cases) { json_str = "{\"Error\":\"no case\"}"; } else if (m_exeType != "auto") { // skip to next set if widget crash when run manual cases if (g_run_wiget == true) { // check whether widget is running DBG_ONLY("----do widget live checking"); //------------------------------------------------------------------------------------------------------------------------------------------- #if defined(__WIN32__) || defined(__WIN64__) string cmd = "tasklist | findstr xwalk.exe"; if (!run_cmd_new(cmd, "xwalk.exe", NULL)) { m_set_finished = true; m_block_finished = true; #else string cmd = "ps ax | grep " + m_suite_id + " | grep -v grep | awk '{print $NF}'"; if (!run_cmd_new(cmd, m_suite_id, NULL)) { DBG_ONLY ("----widget is not online, finish the set"); m_set_finished = true; m_block_finished = true; #endif } else { set_timer(60); // continue to set timer for manual cases } } } else if (m_block_case_index < m_block_case_count) { g_error_code = 3; checkResult(&m_test_cases[m_block_case_index]); json_str = "{\"OK\":\"send timeout\"}"; } else { json_str = "{\"Error\":\"case out of index\"}"; } if (g_show_log) DBG_ONLY(json_str); } void HttpServer::print_info_string(int case_index) { if (g_show_log) { DBG_ONLY(endl << "execute case: "); DBG_ONLY(m_suite_name << " # " << m_test_cases[case_index].case_id << " ..(" << m_test_cases[case_index].result << ")"); if (m_test_cases[case_index].result != "PASS") // print error message if case not pass DBG_ONLY(m_test_cases[case_index].std_out); } pthread_mutex_lock(&result_mutex); m_result.append(m_test_cases[case_index].result_to_json()); if (m_exeType == "auto") { if (m_block_case_index < m_block_case_count) { m_block_case_index++; m_total_case_index++; } } pthread_mutex_unlock(&result_mutex); } // prepare to run current auto case by set the start time, etc. bool HttpServer::get_auto_case(string content, string * type) { if (!m_killing_widget) { if (content != "") { string value = content.substr(content.find("=") + 1); if (value.length() > 0) { if (m_running_session == value) { if (m_block_case_index < m_block_case_count) { set_timer(m_test_cases[m_block_case_index].timeout_value + 10); // +10 is to avoid dup result from suite if case timeout set_cl_timeout(m_test_cases [m_block_case_index]. timeout_value + 10); m_test_cases [m_block_case_index]. set_start_at(); if (g_show_log) DBG_ONLY(endl << "start time: " << m_test_cases [m_block_case_index]. start_at); return true; } else { if (g_show_log) DBG_ONLY(endl << "[ no auto case is available any more ]"); *type = "none"; m_block_finished = true; if (m_current_block_index == m_totalBlocks) m_set_finished = true; // the set is finished if current block is the last block } } else { if (g_show_log) DBG_ONLY ("[ Error: invalid session ID ]"); *type = "invalid"; } } } } else { if (g_show_log) DBG_ONLY(endl << "[ restart client process is activated, exit current client ]"); *type = "stop"; } return false; } void *socket_thread(void *para) { #if defined(__WIN32__) || defined(__WIN64__) #else sigset_t set; int s; /* Block SIGALRM; other threads created by main() will inherit a copy of the signal mask. */ sigemptyset(&set); sigaddset(&set, SIGALRM); s = pthread_sigmask(SIG_BLOCK, &set, NULL); if ((s != 0) && (g_show_log)) DBG_ONLY("fail to pthread_sigmask !!!"); #endif struct sockaddr_in clientAddr; int addr_len = sizeof(clientAddr); while (httpserver.gIsRun) { #if defined(__WIN32__) || defined(__WIN64__) int clientsocket = accept(serversocket, (struct sockaddr *)&clientAddr, (int *)&addr_len); #else int clientsocket = accept(serversocket, (struct sockaddr *)&clientAddr, (socklen_t *) & addr_len); #endif if (clientsocket < 0) { if (g_show_log) DBG_ONLY("fail to accept client socket !!!"); } else { thread_info tinfo; tinfo.server = &httpserver; tinfo.clientsocket = clientsocket; if (g_show_log) DBG_ONLY("open " << clientsocket); pthread_create(&tinfo.thread_id, NULL, processthread, &tinfo); //if (tinfo.thread_id != 0) pthread_detach(tinfo.thread_id);// this will release resource after threat exit. otherwise it may not execute the thread after run for a while. but still cause some strange issue #if defined(__WIN32__) || defined(__WIN64__) if (tinfo.thread_id.p) pthread_join(tinfo.thread_id, NULL); else if (g_show_log) DBG_ONLY("fail to create thread !!!"); #else if (tinfo.thread_id != 0) pthread_join(tinfo.thread_id, NULL); else if (g_show_log) DBG_ONLY("fail to create thread !!!"); #endif } } close(serversocket); pthread_exit(NULL); return 0; }
/** * Execute the given command. If the execution fails, the wait_start() * thread in control.c should notice this and send an alert message. * @param S A Service object * @param C A Command object * @param E An optional event object. May be NULL. */ void spawn(Service_T S, command_t C, Event_T E) { pid_t pid; sigset_t mask; sigset_t save; int stat_loc = 0; int exit_status; char date[42]; ASSERT(S); ASSERT(C); if (access(C->arg[0], X_OK) != 0) { LogError("Error: Could not execute %s\n", C->arg[0]); return; } /* * Block SIGCHLD */ sigemptyset(&mask); sigaddset(&mask, SIGCHLD); pthread_sigmask(SIG_BLOCK, &mask, &save); Time_string(Time_now(), date); pid = fork(); if (pid < 0) { LogError("Cannot fork a new process -- %s\n", STRERROR); pthread_sigmask(SIG_SETMASK, &save, NULL); return; } if (pid == 0) { if (C->has_gid) { if (setgid(C->gid) != 0) { stat_loc |= setgid_ERROR; } } if (C->has_uid) { struct passwd *user = getpwuid(C->uid); if (user) { if (initgroups(user->pw_name, getgid()) == 0) { if (setuid(C->uid) != 0) { stat_loc |= setuid_ERROR; } } else { stat_loc |= initgroups_ERROR; } } else { stat_loc |= getpwuid_ERROR; } } set_monit_environment(S, C, E, date); if (! (Run.flags & Run_Daemon)) { for (int i = 0; i < 3; i++) if (close(i) == -1 || open("/dev/null", O_RDWR) != i) stat_loc |= redirect_ERROR; } Util_closeFds(); setsid(); pid = fork(); if (pid < 0) { stat_loc |= fork_ERROR; _exit(stat_loc); } if (pid == 0) { /* * Reset all signals, so the spawned process is *not* created * with any inherited SIG_BLOCKs */ sigemptyset(&mask); pthread_sigmask(SIG_SETMASK, &mask, NULL); signal(SIGINT, SIG_DFL); signal(SIGHUP, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGUSR1, SIG_DFL); signal(SIGPIPE, SIG_DFL); (void) execv(C->arg[0], C->arg); _exit(errno); } /* Exit first child and return errors to parent */ _exit(stat_loc); } /* Wait for first child - aka second parent, to exit */ if (waitpid(pid, &stat_loc, 0) != pid) { LogError("Waitpid error\n"); } exit_status = WEXITSTATUS(stat_loc); if (exit_status & setgid_ERROR) LogError("Failed to change gid to '%d' for '%s'\n", C->gid, C->arg[0]); if (exit_status & setuid_ERROR) LogError("Failed to change uid to '%d' for '%s'\n", C->uid, C->arg[0]); if (exit_status & initgroups_ERROR) LogError("initgroups for UID %d failed when executing '%s'\n", C->uid, C->arg[0]); if (exit_status & fork_ERROR) LogError("Cannot fork a new process for '%s'\n", C->arg[0]); if (exit_status & redirect_ERROR) LogError("Cannot redirect IO to /dev/null for '%s'\n", C->arg[0]); if (exit_status & getpwuid_ERROR) LogError("UID %d not found on the system when executing '%s'\n", C->uid, C->arg[0]); /* * Restore the signal mask */ pthread_sigmask(SIG_SETMASK, &save, NULL); /* * We do not need to wait for the second child since we forked twice, * the init system-process will wait for it. So we just return */ }
SignalHandlers() { memset(signaled, 0, sizeof(signaled)); pthread_sigmask(SIG_SETMASK, NULL, &oldSet); }
void * token_depositing_thread_function(void *args){ pthread_sigmask(SIG_BLOCK, &set, 0); long local_token_created_count = 0; long local_token_dropped_count = 0; float local_total_packet_time_in_Q1 = 0.0; int stop_flag = 0; struct timeval current_time; while(1){ /* Sleep for needed time */ usleep(token_arrival_time * 1000000.0); /* Lock the mutex */ pthread_mutex_lock(&mutex); if(cntrl_c_signal){ stop_flag = 1; } else{ local_token_created_count++; /* Increment token count */ if(number_of_tokens_in_bucket < bucket_capacity){ number_of_tokens_in_bucket++; gettimeofday(¤t_time, NULL); printf("%012.3fms: token t%ld arrives, token bucket now has %ld tokens\n",calculate_time_difference(current_time,emulation_start_time),local_token_created_count,number_of_tokens_in_bucket); } else { local_token_dropped_count++; gettimeofday(¤t_time, NULL); printf("%012.3fms: token t%ld arrives, dropped\n",calculate_time_difference(current_time,emulation_start_time),local_token_created_count); } if(!My402ListEmpty(&Q1)){ My402ListElem * temp_arrival_thread_element = My402ListLast(&Q1); struct packet * temp_arrival_thread_packet = (struct packet *)(temp_arrival_thread_element->obj); /* Move the first packet to q2 if there are enough tokens */ if(number_of_tokens_in_bucket >= temp_arrival_thread_packet->tokens_needed){ int is_empty = My402ListEmpty(&Q2); number_of_tokens_in_bucket = number_of_tokens_in_bucket - temp_arrival_thread_packet->tokens_needed; My402ListUnlink(&Q1,temp_arrival_thread_element); gettimeofday(¤t_time, NULL); printf("%012.3fms: p%ld leaves Q1, time in Q1 = %.3fms, token bucket now has %ld token\n",calculate_time_difference(current_time,emulation_start_time),temp_arrival_thread_packet->id,calculate_time_difference(current_time, temp_arrival_thread_packet->updation_time),number_of_tokens_in_bucket); local_total_packet_time_in_Q1 = local_total_packet_time_in_Q1 + calculate_time_difference(current_time, temp_arrival_thread_packet->updation_time); gettimeofday(&temp_arrival_thread_packet->updation_time, NULL); My402ListPrepend(&Q2, temp_arrival_thread_packet); gettimeofday(¤t_time, NULL); printf("%012.3fms: p%ld enters Q2\n",calculate_time_difference(current_time,emulation_start_time),temp_arrival_thread_packet->id); if(is_empty){ pthread_cond_broadcast(&condition_variable); } } temp_arrival_thread_element = NULL; temp_arrival_thread_packet = NULL; } else { if(packet_arrival_thread_stop){ stop_flag = 1; } } if(server_thread_stop){ stop_flag = 1; } } /* Unloack the mutex */ pthread_mutex_unlock(&mutex); if(stop_flag){ pthread_mutex_lock(&mutex); if(local_total_packet_time_in_Q1 != 0.0){ if(average_number_of_packets_in_Q1 == -1.0){ average_number_of_packets_in_Q1 = 0.0; } average_number_of_packets_in_Q1 = average_number_of_packets_in_Q1 + local_total_packet_time_in_Q1; } average_number_of_packets_in_Q1 = average_number_of_packets_in_Q1 + local_total_packet_time_in_Q1; if(local_token_created_count !=0){ token_drop_probability = (float)local_token_dropped_count / (float)local_token_created_count; } if(packet_arrival_thread_stop && !server_thread_stop){ pthread_cond_broadcast(&condition_variable); } pthread_mutex_unlock(&mutex); break; } } pthread_exit(0); return NULL; }
void *clamukofsth(void *arg) { struct thrarg *tharg = (struct thrarg *) arg; sigset_t sigset; struct sigaction act; pthread_t *clamuko_pids = NULL; const char *groupname = "ClamAV"; int count; int started; /* is another server thread already working? */ if(pthread_mutex_trylock(&running_mutex)) return NULL; /* ignore all signals except SIGUSR1 */ sigfillset(&sigset); sigdelset(&sigset, SIGUSR1); /* The behavior of a process is undefined after it ignores a * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ sigdelset(&sigset, SIGFPE); sigdelset(&sigset, SIGILL); sigdelset(&sigset, SIGSEGV); #ifdef SIGBUS sigdelset(&sigset, SIGBUS); #endif pthread_sigmask(SIG_SETMASK, &sigset, NULL); count = optget(tharg->opts, "ClamukoScannerCount")->numarg; if(count < 1) goto out; clamuko_pids = calloc(count, sizeof(pthread_t)); if(!clamuko_pids) goto out; if(setup_shutdown_handle(groupname)) goto out; act.sa_handler = clamuko_exit; sigfillset(&(act.sa_mask)); sigaction(SIGUSR1, &act, NULL); sigaction(SIGSEGV, &act, NULL); for(started = 0; started < count; started++) { pthread_attr_t clamuko_attr; if(pthread_attr_init(&clamuko_attr)) break; pthread_attr_setdetachstate(&clamuko_attr, PTHREAD_CREATE_JOINABLE); if(pthread_create(&clamuko_pids[started], &clamuko_attr, clamuko_scanth, tharg)) break; logg("Clamuko: Started scanner thread %d.\n", started); } pthread_cond_wait(&shutdown_cond, &running_mutex); logg("Clamuko: Stop signal received.\n"); shutdown_clamuko(); for(started-- ; started >= 0; started--) { logg("Clamuko: Waiting for scanner thread %d to finish.\n", started); pthread_join(clamuko_pids[started], NULL); } logg("Clamuko: Stopped.\n"); out: if(clamuko_pids) free(clamuko_pids); pthread_mutex_unlock(&running_mutex); return NULL; }
} DirectResult direct_socketpair( int __domain, int __type, int __protocol, int __fds[2] ) { if (socketpair( __domain, __type, __protocol, __fds )) return errno2result( errno ); return DR_OK; } DirectResult direct_sigprocmask( int __how, __const sigset_t *__restrict __set, sigset_t *__restrict __oset ) { int ret = pthread_sigmask( __how, __set, __oset ); return errno2result( ret ); } uid_t direct_getuid() { return getuid(); } uid_t direct_geteuid() { return geteuid(); }
int main (int argc, char **argv) { starter_config_t *cfg = NULL; starter_config_t *new_cfg; starter_conn_t *conn, *conn2; starter_ca_t *ca, *ca2; struct sigaction action; struct stat stb; int i; int id = 1; struct timespec ts; unsigned long auto_update = 0; time_t last_reload; bool no_fork = FALSE; bool attach_gdb = FALSE; bool load_warning = FALSE; library_init(NULL); atexit(library_deinit); libhydra_init("starter"); atexit(libhydra_deinit); /* parse command line */ for (i = 1; i < argc; i++) { if (streq(argv[i], "--debug")) { current_loglevel = 2; } else if (streq(argv[i], "--debug-more")) { current_loglevel = 3; } else if (streq(argv[i], "--debug-all")) { current_loglevel = 4; } else if (streq(argv[i], "--nolog")) { current_loglevel = 0; } else if (streq(argv[i], "--nofork")) { no_fork = TRUE; } else if (streq(argv[i], "--attach-gdb")) { no_fork = TRUE; attach_gdb = TRUE; } else if (streq(argv[i], "--auto-update") && i+1 < argc) { auto_update = atoi(argv[++i]); if (!auto_update) usage(argv[0]); } else if (streq(argv[i], "--daemon") && i+1 < argc) { daemon_name = argv[++i]; } else { usage(argv[0]); } } if (!set_daemon_name()) { DBG1(DBG_APP, "unable to set daemon name"); exit(LSB_RC_FAILURE); } init_log("ipsec_starter"); DBG1(DBG_APP, "Starting %sSwan "VERSION" IPsec [starter]...", lib->settings->get_bool(lib->settings, "charon.i_dont_care_about_security_and_use_aggressive_mode_psk", FALSE) ? "weak" : "strong"); #ifdef LOAD_WARNING load_warning = TRUE; #endif if (lib->settings->get_bool(lib->settings, "starter.load_warning", load_warning)) { if (lib->settings->get_str(lib->settings, "charon.load", NULL)) { DBG1(DBG_APP, "!! Your strongswan.conf contains manual plugin load options for charon."); DBG1(DBG_APP, "!! This is recommended for experts only, see"); DBG1(DBG_APP, "!! http://wiki.strongswan.org/projects/strongswan/wiki/PluginLoad"); } } /* verify that we can start */ if (getuid() != 0) { DBG1(DBG_APP, "permission denied (must be superuser)"); cleanup(); exit(LSB_RC_NOT_ALLOWED); } if (check_pid(pid_file)) { DBG1(DBG_APP, "%s is already running (%s exists) -- skipping daemon start", daemon_name, pid_file); } else { _action_ |= FLAG_ACTION_START_CHARON; } if (stat(DEV_RANDOM, &stb) != 0) { DBG1(DBG_APP, "unable to start strongSwan IPsec -- no %s!", DEV_RANDOM); cleanup(); exit(LSB_RC_FAILURE); } if (stat(DEV_URANDOM, &stb)!= 0) { DBG1(DBG_APP, "unable to start strongSwan IPsec -- no %s!", DEV_URANDOM); cleanup(); exit(LSB_RC_FAILURE); } cfg = confread_load(CONFIG_FILE); if (cfg == NULL || cfg->err > 0) { DBG1(DBG_APP, "unable to start strongSwan -- fatal errors in config"); if (cfg) { confread_free(cfg); } cleanup(); exit(LSB_RC_INVALID_ARGUMENT); } /* determine if we have a native netkey IPsec stack */ if (!starter_netkey_init()) { DBG1(DBG_APP, "no netkey IPsec stack detected"); if (!starter_klips_init()) { DBG1(DBG_APP, "no KLIPS IPsec stack detected"); DBG1(DBG_APP, "no known IPsec stack detected, ignoring!"); } } last_reload = time_monotonic(NULL); if (check_pid(starter_pid_file)) { DBG1(DBG_APP, "starter is already running (%s exists) -- no fork done", starter_pid_file); confread_free(cfg); cleanup(); exit(LSB_RC_SUCCESS); } #ifdef GENERATE_SELFCERT generate_selfcert(); #endif /* fork if we're not debugging stuff */ if (!no_fork) { log_to_stderr = FALSE; switch (fork()) { case 0: { int fnull; close_log(); closefrom(3); fnull = open("/dev/null", O_RDWR); if (fnull >= 0) { dup2(fnull, STDIN_FILENO); dup2(fnull, STDOUT_FILENO); dup2(fnull, STDERR_FILENO); close(fnull); } setsid(); init_log("ipsec_starter"); } break; case -1: DBG1(DBG_APP, "can't fork: %s", strerror(errno)); break; default: confread_free(cfg); cleanup(); exit(LSB_RC_SUCCESS); } } /* save pid file in /var/run/starter[.daemon_name].pid */ { FILE *fd = fopen(starter_pid_file, "w"); if (fd) { fprintf(fd, "%u\n", getpid()); fclose(fd); } } /* we handle these signals only in pselect() */ memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGHUP); sigaddset(&action.sa_mask, SIGINT); sigaddset(&action.sa_mask, SIGTERM); sigaddset(&action.sa_mask, SIGQUIT); sigaddset(&action.sa_mask, SIGALRM); sigaddset(&action.sa_mask, SIGUSR1); pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL); /* install a handler for fatal signals */ action.sa_handler = fatal_signal_handler; sigaction(SIGSEGV, &action, NULL); sigaction(SIGILL, &action, NULL); sigaction(SIGBUS, &action, NULL); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); /* install main signal handler */ action.sa_handler = signal_handler; sigaction(SIGHUP, &action, NULL); sigaction(SIGINT, &action, NULL); sigaction(SIGTERM, &action, NULL); sigaction(SIGQUIT, &action, NULL); sigaction(SIGALRM, &action, NULL); sigaction(SIGUSR1, &action, NULL); /* this is not blocked above as we want to receive it asynchronously */ sigaction(SIGCHLD, &action, NULL); /* empty mask for pselect() call below */ sigemptyset(&action.sa_mask); for (;;) { /* * Stop charon (if started) and exit */ if (_action_ & FLAG_ACTION_QUIT) { if (starter_charon_pid()) { starter_stop_charon(); } starter_netkey_cleanup(); confread_free(cfg); unlink(starter_pid_file); cleanup(); DBG1(DBG_APP, "ipsec starter stopped"); close_log(); exit(LSB_RC_SUCCESS); } /* * Delete all connections. Will be added below */ if (_action_ & FLAG_ACTION_RELOAD) { if (starter_charon_pid()) { for (conn = cfg->conn_first; conn; conn = conn->next) { if (conn->state == STATE_ADDED) { if (starter_charon_pid()) { if (conn->startup == STARTUP_ROUTE) { starter_stroke_unroute_conn(conn); } starter_stroke_del_conn(conn); } conn->state = STATE_TO_ADD; } } for (ca = cfg->ca_first; ca; ca = ca->next) { if (ca->state == STATE_ADDED) { if (starter_charon_pid()) { starter_stroke_del_ca(ca); } ca->state = STATE_TO_ADD; } } } _action_ &= ~FLAG_ACTION_RELOAD; } /* * Update configuration */ if (_action_ & FLAG_ACTION_UPDATE) { DBG2(DBG_APP, "Reloading config..."); new_cfg = confread_load(CONFIG_FILE); if (new_cfg && (new_cfg->err == 0)) { /* Switch to new config. New conn will be loaded below */ /* Look for new connections that are already loaded */ for (conn = cfg->conn_first; conn; conn = conn->next) { if (conn->state == STATE_ADDED) { for (conn2 = new_cfg->conn_first; conn2; conn2 = conn2->next) { if (conn2->state == STATE_TO_ADD && starter_cmp_conn(conn, conn2)) { conn->state = STATE_REPLACED; conn2->state = STATE_ADDED; conn2->id = conn->id; break; } } } } /* Remove conn sections that have become unused */ for (conn = cfg->conn_first; conn; conn = conn->next) { if (conn->state == STATE_ADDED) { if (starter_charon_pid()) { if (conn->startup == STARTUP_ROUTE) { starter_stroke_unroute_conn(conn); } starter_stroke_del_conn(conn); } } } /* Look for new ca sections that are already loaded */ for (ca = cfg->ca_first; ca; ca = ca->next) { if (ca->state == STATE_ADDED) { for (ca2 = new_cfg->ca_first; ca2; ca2 = ca2->next) { if (ca2->state == STATE_TO_ADD && starter_cmp_ca(ca, ca2)) { ca->state = STATE_REPLACED; ca2->state = STATE_ADDED; break; } } } } /* Remove ca sections that have become unused */ for (ca = cfg->ca_first; ca; ca = ca->next) { if (ca->state == STATE_ADDED) { if (starter_charon_pid()) { starter_stroke_del_ca(ca); } } } confread_free(cfg); cfg = new_cfg; } else { DBG1(DBG_APP, "can't reload config file due to errors -- keeping old one"); if (new_cfg) { confread_free(new_cfg); } } _action_ &= ~FLAG_ACTION_UPDATE; last_reload = time_monotonic(NULL); } /* * Start daemon */ if (_action_ & FLAG_ACTION_START_CHARON) { if (cfg->setup.charonstart && !starter_charon_pid()) { DBG2(DBG_APP, "Attempting to start %s...", daemon_name); if (starter_start_charon(cfg, no_fork, attach_gdb)) { /* schedule next try */ alarm(CHARON_RESTART_DELAY); } starter_stroke_configure(cfg); } _action_ &= ~FLAG_ACTION_START_CHARON; for (ca = cfg->ca_first; ca; ca = ca->next) { if (ca->state == STATE_ADDED) { ca->state = STATE_TO_ADD; } } for (conn = cfg->conn_first; conn; conn = conn->next) { if (conn->state == STATE_ADDED) { conn->state = STATE_TO_ADD; } } } /* * Add stale conn and ca sections */ if (starter_charon_pid()) { for (ca = cfg->ca_first; ca; ca = ca->next) { if (ca->state == STATE_TO_ADD) { if (starter_charon_pid()) { starter_stroke_add_ca(ca); } ca->state = STATE_ADDED; } } for (conn = cfg->conn_first; conn; conn = conn->next) { if (conn->state == STATE_TO_ADD) { if (conn->id == 0) { /* affect new unique id */ conn->id = id++; } if (starter_charon_pid()) { starter_stroke_add_conn(cfg, conn); } conn->state = STATE_ADDED; if (conn->startup == STARTUP_START) { if (starter_charon_pid()) { starter_stroke_initiate_conn(conn); } } else if (conn->startup == STARTUP_ROUTE) { if (starter_charon_pid()) { starter_stroke_route_conn(conn); } } } } } /* * If auto_update activated, when to stop select */ if (auto_update) { time_t now = time_monotonic(NULL); ts.tv_sec = (now < last_reload + auto_update) ? (last_reload + auto_update - now) : 0; ts.tv_nsec = 0; } /* * Wait for something to happen */ if (!_action_ && pselect(0, NULL, NULL, NULL, auto_update ? &ts : NULL, &action.sa_mask) == 0) { /* timeout -> auto_update */ _action_ |= FLAG_ACTION_UPDATE; } } exit(LSB_RC_SUCCESS); }
BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { pid_t pid; int flags; int numArgs; LPSTR* pArgs = NULL; char** envp = NULL; char* filename = NULL; HANDLE thread; HANDLE process; WINPR_ACCESS_TOKEN* token; LPTCH lpszEnvironmentBlock; BOOL ret = FALSE; sigset_t oldSigMask; sigset_t newSigMask; BOOL restoreSigMask = FALSE; pid = 0; numArgs = 0; lpszEnvironmentBlock = NULL; pArgs = CommandLineToArgvA(lpCommandLine, &numArgs); if (!pArgs) return FALSE; flags = 0; token = (WINPR_ACCESS_TOKEN*) hToken; if (lpEnvironment) { envp = EnvironmentBlockToEnvpA(lpEnvironment); } else { lpszEnvironmentBlock = GetEnvironmentStrings(); if (!lpszEnvironmentBlock) goto finish; envp = EnvironmentBlockToEnvpA(lpszEnvironmentBlock); } if (!envp) goto finish; filename = FindApplicationPath(pArgs[0]); if (NULL == filename) goto finish; /* block all signals so that the child can safely reset the caller's handlers */ sigfillset(&newSigMask); restoreSigMask = !pthread_sigmask(SIG_SETMASK, &newSigMask, &oldSigMask); /* fork and exec */ pid = fork(); if (pid < 0) { /* fork failure */ goto finish; } if (pid == 0) { /* child process */ #ifndef __sun int maxfd; #endif int fd; int sig; sigset_t set; struct sigaction act; /* set default signal handlers */ memset(&act, 0, sizeof(act)); act.sa_handler = SIG_DFL; act.sa_flags = 0; sigemptyset(&act.sa_mask); for (sig = 1; sig < NSIG; sig++) sigaction(sig, &act, NULL); /* unblock all signals */ sigfillset(&set); pthread_sigmask(SIG_UNBLOCK, &set, NULL); if (lpStartupInfo) { int handle_fd; handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdOutput); if (handle_fd != -1) dup2(handle_fd, STDOUT_FILENO); handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdError); if (handle_fd != -1) dup2(handle_fd, STDERR_FILENO); handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdInput); if (handle_fd != -1) dup2(handle_fd, STDIN_FILENO); } #ifdef __sun closefrom(3); #else #ifdef F_MAXFD // on some BSD derivates maxfd = fcntl(0, F_MAXFD); #else maxfd = sysconf(_SC_OPEN_MAX); #endif for(fd=3; fd<maxfd; fd++) close(fd); #endif // __sun if (token) { if (token->GroupId) { int rc = setgid((gid_t) token->GroupId); if (rc < 0) { } else { initgroups(token->Username, (gid_t) token->GroupId); } } if (token->UserId) setuid((uid_t) token->UserId); } /* TODO: add better cwd handling and error checking */ if (lpCurrentDirectory && strlen(lpCurrentDirectory) > 0) chdir(lpCurrentDirectory); if (execve(filename, pArgs, envp) < 0) { /* execve failed - end the process */ _exit(1); } } else { /* parent process */ } process = CreateProcessHandle(pid); if (!process) { goto finish; } thread = CreateNoneHandle(); if (!thread) { ProcessHandleCloseHandle(process); goto finish; } lpProcessInformation->hProcess = process; lpProcessInformation->hThread = thread; lpProcessInformation->dwProcessId = (DWORD) pid; lpProcessInformation->dwThreadId = (DWORD) pid; ret = TRUE; finish: /* restore caller's original signal mask */ if (restoreSigMask) pthread_sigmask(SIG_SETMASK, &oldSigMask, NULL); free(filename); if (pArgs) { HeapFree(GetProcessHeap(), 0, pArgs); } if (lpszEnvironmentBlock) FreeEnvironmentStrings(lpszEnvironmentBlock); if (envp) { int i = 0; while (envp[i]) { free(envp[i]); i++; } free(envp); } return ret; }