/* * called at exit */ static void cleanup(void) { log_notice("Exiting"); if(!intr) { /* We are not in the interrupt context */ if(md5ctxp != NULL) { free_MD5_CTX(md5ctxp); } if(pq != NULL) { off_t highwater = 0; size_t maxregions = 0; (void) pq_highwater(pq, &highwater, &maxregions); (void) pq_close(pq); pq = NULL; if(feed_close) (*feed_close)(ifd); ifd = -1; log_notice(" Queue usage (bytes):%8ld", (long)highwater); log_notice(" (nregions):%8ld", (long)maxregions); log_notice(" Duplicates rejected:%8lu", ndups); } (*prod_stats)(); (*feed_stats)(); } log_fini(); }
static int sender_start( const feedtypet feedtype) { // The following ensures that the first product-index will be 0 int status = pim_delete(NULL, feedtype); if (status) { LOG_ADD1("Couldn't delete product-index map for feedtype %#lx", feedtype); } else { status = createEmptyProductQueue(UP7_PQ_PATHNAME); if (status) { LOG_ADD1("Couldn't create empty product queue \"%s\"", UP7_PQ_PATHNAME); } else { // Thread-safe because 2 threads: upstream LDM-7 & product insertion. status = pq_open(getQueuePath(), PQ_READONLY | PQ_THREADSAFE, &pq); if (status) { LOG_ADD1("Couldn't open product-queue \"%s\"", getQueuePath()); } else { McastInfo* mcastInfo; status = setMcastInfo(&mcastInfo, feedtype); if (status) { LOG_ADD0("Couldn't set multicast information"); } else { status = mlsm_clear(); status = mlsm_addPotentialSender(mcastInfo, 2, LOCAL_HOST, UP7_PQ_PATHNAME); if (status) { LOG_ADD0("mlsm_addPotentialSender() failure"); } else { // Starts the sender on a new thread status = sender_spawn(); if (status) { LOG_ADD0("Couldn't spawn sender"); } else { done = 0; } } mi_free(mcastInfo); } // `mcastInfo` allocated if (status) (void)pq_close(pq); } // Product-queue open if (status) (void)deleteProductQueue(UP7_PQ_PATHNAME); } // empty product-queue created } // product-index map deleted return status; }
static void sender_insertProducts(void) { pqueue* pq; int status = pq_open(UP7_PQ_PATHNAME, 0, &pq); CU_ASSERT_EQUAL_FATAL(status, 0); product prod; prod_info* info = &prod.info; char ident[80]; void* data = NULL; unsigned short xsubi[3] = {(unsigned short)1234567890, (unsigned short)9876543210, (unsigned short)1029384756 }; info->feedtype = EXP; info->ident = ident; info->origin = "localhost"; (void)memset(info->signature, 0, sizeof(info->signature)); for (int i = 0; i < NUM_PRODS; i++) { const unsigned size = MAX_PROD_SIZE*erand48(xsubi) + 0.5; const ssize_t nbytes = snprintf(ident, sizeof(ident), "%d", i); CU_ASSERT_TRUE_FATAL(nbytes >= 0 && nbytes < sizeof(ident)); status = set_timestamp(&info->arrival); CU_ASSERT_EQUAL_FATAL(status, 0); info->seqno = i; uint32_t signet = htonl(i); (void)memcpy(info->signature+sizeof(signaturet)-sizeof(signet), &signet, sizeof(signet)); info->sz = size; data = realloc(data, size); CU_ASSERT_PTR_NOT_NULL(data); prod.data = data; status = pq_insert(pq, &prod); CU_ASSERT_EQUAL_FATAL(status, 0); char buf[LDM_INFO_MAX]; LOG_ADD1("Inserted: prodInfo=\"%s\"", s_prod_info(buf, sizeof(buf), info, 1)); log_log(LOG_INFO); struct timespec duration; duration.tv_sec = 0; duration.tv_nsec = 5000000; // 5 ms status = nanosleep(&duration, NULL); CU_ASSERT_EQUAL_FATAL(status, 0); } free(data); status = pq_close(pq); CU_ASSERT_EQUAL_FATAL(status, 0); }
void cleanup(void) { unotice("Exiting"); if(pq && !intr) (void)pq_close(pq); (void) closeulog(); }
void cleanup (void) { if (pq) { (void) pq_close (pq); pq = NULL; } log_fini(); }
static void pti_fini(void) { if (pq) { (void)pq_close(pq); pq = NULL; } if (prod.data) { free(prod.data); prod.data = NULL; } }
static void cleanup(void){ /* * If malloc() was used for prod.data, we leave it to the OS to free * the memory allocated. */ if(g.pq != NULL) { pq_close(g.pq); g.pq = NULL; } if((g.fd != -1) && (g.fd != STDIN_FILENO)){ close(g.fd); g.fd = -1; } }
static void cleanup(void) { log_notice("Exiting"); dump_stats(&stats); if(pq != NULL) { (void)pq_close(pq); pq = NULL; } log_fini(); }
void cleanup(void) { if (pq) { #if !USE_MMAP if (!pqeIsNone(pqeIndex)) (void)pqe_discard(pq, pqeIndex); #endif (void) pq_close(pq); pq = NULL; } (void)closeulog(); }
void cleanup(void) { unotice("Exiting"); if(act_pid != -1) { (void)signal(SIGCHLD, SIG_IGN); kill(act_pid, SIGTERM); (void) reap_act(0); } if(opq != NULL) { off_t highwater = 0; size_t maxregions = 0; (void) pq_highwater(opq, &highwater, &maxregions); (void) pq_close(opq); opq = NULL; unotice(" Queue usage (bytes):%8ld", (long)highwater); unotice(" (nregions):%8ld", (long)maxregions); } if(pq != NULL) { (void) pq_close(pq); pq = NULL; } dump_stats(); (void) closeulog(); }
static int createEmptyProductQueue( const char* const pathname) { pqueue* pq; int status = pq_create(pathname, 0666, PQ_DEFAULT, 0, PQ_SIZE, NUM_PQ_SLOTS, &pq); // PQ_DEFAULT => clobber existing if (status == 0) { status = pq_close(pq); if (status) { LOG_ADD1("Couldn't close product-queue \"%s\"", pathname); } } return status; }
/* * called at exit */ static void cleanup(void) { log_notice("Exiting"); if (done) { /* * We are not in the interrupt context, so these can be performed * safely. */ fl_closeAll(); if (pq) (void)pq_close(pq); if (!tvEqual(palt_last_insertion, TS_ZERO)) { timestampt now; (void)set_timestamp(&now); log_notice("Behind by %g s", d_diff_timestamp(&now, &palt_last_insertion)); if (stateWrite(&palt_last_insertion) < 0) { log_error("Couldn't save insertion-time of last processed " "data-product"); } } while (reap(-1, WNOHANG) > 0) /*EMPTY*/; } if(shmid != -1) { log_notice("Deleting shared segment."); shmctl(shmid, IPC_RMID, NULL); } if(semid != -1) { semctl(semid, 0, IPC_RMID); } log_fini(); }
static void cleanup(void){ /* * If malloc() was used for prod.data, we leave it to the OS to free * the memory allocated (g.dynamic_pool). */ if(g.pq != NULL) { pq_close(g.pq); g.pq = NULL; } if(g.strp != NULL) { strsplit_delete(g.strp); g.strp = NULL; } if((g.fd != -1) && (g.fd != STDIN_FILENO)){ close(g.fd); g.fd = -1; } }
hiya_reply_t* hiya_6_svc( prod_class_t *offered, struct svc_req *rqstp) { const char* const pqfname = getQueuePath(); static hiya_reply_t reply; SVCXPRT * const xprt = rqstp->rq_xprt; struct sockaddr_in *upAddr = (struct sockaddr_in*) svc_getcaller(xprt); const char *upName = hostbyaddr(upAddr); int error; int isPrimary; unsigned int maxHereis; static prod_class_t *accept; /* * Open the product-queue for writing. It will be closed by cleanup() * during process termination. */ if (pq) { (void) pq_close(pq); pq = NULL; } error = pq_open(pqfname, PQ_DEFAULT, &pq); if (error) { err_log_and_free(ERR_NEW2(error, NULL, "Couldn't open product-queue \"%s\" for writing: %s", pqfname, PQ_CORRUPT == error ? "The product-queue is inconsistent" : strerror(error)), ERR_FAILURE); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } /* else */ error = down6_init(upName, upAddr, pqfname, pq); if (error) { uerror("Couldn't initialize downstream LDM"); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } else { uinfo("Downstream LDM initialized"); } /* * The previous "accept" is freed here -- rather than freeing the * soon-to-be-allocated "accept" at the end of its block -- because it can * be used in the reply. */ if (accept) { free_prod_class(accept); /* NULL safe */ accept = NULL; } error = lcf_reduceToAcceptable(upName, inet_ntoa(upAddr->sin_addr), offered, &accept, &isPrimary); maxHereis = isPrimary ? UINT_MAX : 0; if (error) { serror("Couldn't validate HIYA"); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } else { if (ulogIsDebug()) udebug("intersection: %s", s_prod_class(NULL, 0, accept)); if (accept->psa.psa_len == 0) { uwarn("Empty intersection of HIYA offer from %s (%s) and ACCEPT " "entries", upName, s_prod_class(NULL, 0, offered)); svcerr_weakauth(xprt); svc_destroy(xprt); exit(0); } else { error = down6_set_prod_class(accept); if (error) { if (DOWN6_SYSTEM_ERROR == error) { serror("Couldn't set product class: %s", s_prod_class(NULL, 0, accept)); } else { uerror("Couldn't set product class: %s", s_prod_class(NULL, 0, accept)); } svcerr_systemerr(xprt); svc_destroy(xprt); exit(EXIT_FAILURE); } /* else */ if (clss_eq(offered, accept)) { unotice("hiya6: %s", s_prod_class(NULL, 0, offered)); reply.code = OK; reply.hiya_reply_t_u.max_hereis = maxHereis; } else { if (ulogIsVerbose()) { char off[512]; char acc[512]; (void) s_prod_class(off, sizeof(off), offered), (void) s_prod_class( acc, sizeof(acc), accept); uinfo("hiya6: RECLASS: %s -> %s", off, acc); } reply.code = RECLASS; reply.hiya_reply_t_u.feedPar.prod_class = accept; reply.hiya_reply_t_u.feedPar.max_hereis = maxHereis; } } /* product-intersection != empty set */ } /* successful acl_check_hiya() */ return &reply; }
int main(int ac, char *av[]) { int pflags = PQ_NOCLOBBER; off_t initialsz = 0; size_t nproducts = 0; pqueue *pq = NULL; int errnum = 0; /* * initialize logger */ (void)log_init(av[0]); int ch; char *qopt = NULL; char *sopt = NULL; char *Sopt = NULL; extern char *optarg; extern int optind; const char* pqfname = getQueuePath(); while ((ch = getopt(ac, av, "xvcfq:s:S:l:")) != EOF) switch (ch) { case 'v': if (!log_is_enabled_info) (void)log_set_level(LOG_LEVEL_INFO); break; case 'c': pflags &= ~PQ_NOCLOBBER; break; case 'f': pflags |= PQ_SPARSE; break; case 's': sopt = optarg; break; case 'S': Sopt = optarg; break; case 'q': qopt = optarg; break; case 'x': (void)log_set_level(LOG_LEVEL_DEBUG); break; case 'l': (void)log_set_destination(optarg); break; case '?': usage(av[0]); break; } if(ac - optind > 1) { if(sopt) usage(av[0]); sopt = av[ac - 2]; } if(ac - optind > 0) { if(qopt) usage(av[0]); qopt = av[ac - 1]; } if(qopt) { pqfname = qopt ; setQueuePath(qopt); } if (sopt) { char* cp; int exponent = 0; errno = 0; initialsz = strtol(sopt, &cp, 0); if (0 != errno) { initialsz = 0; /* trigger error below */ } else { switch (*cp) { case 0: break; case 'k': case 'K': exponent = 1; break; case 'm': case 'M': exponent = 2; break; case 'g': case 'G': exponent = 3; break; default: initialsz = 0; /* trigger error below */ break; } if (0 < initialsz) { int i; for (i = 0; i < exponent; i++) { initialsz *= 1000; if (0 >= initialsz) { fprintf(stderr, "Size \"%s\" too big\n", sopt); usage(av[0]); } } } } } if(initialsz <= 0) { if(sopt) fprintf(stderr, "Illegal size \"%s\"\n", sopt); else fprintf(stderr, "No size specified\n"); usage(av[0]); } if(Sopt != NULL) { nproducts = (size_t)atol(Sopt); if(nproducts == 0) { fprintf(stderr, "Illegal nproducts \"%s\"\n", Sopt); } } else { #define PQ_AVG_PRODUCT_SIZE 51000 // approximate mean size on 2014-08-21 /* For default number of product slots, use average product size estimate */ nproducts = initialsz/PQ_AVG_PRODUCT_SIZE; } log_info_q("Creating %s, %ld bytes, %ld products.\n", pqfname, (long)initialsz, (long)nproducts); errnum = pq_create(pqfname, 0666, pflags, 0, initialsz, nproducts, &pq); if(errnum) { fprintf(stderr, "%s: create \"%s\" failed: %s\n", av[0], pqfname, strerror(errnum)); exit(1); } (void)pq_close(pq); return(0); }
int main( int ac, char* av[]) { const char* pqfname = getQueuePath(); int sock = -1; int status; int doSomething = 1; in_addr_t locIpAddr = (in_addr_t) htonl(INADDR_ANY ); unsigned ldmPort = LDM_PORT; ensureDumpable(); /* * deal with the command line, set options */ { extern int optind; extern int opterr; extern char *optarg; int ch; int logmask = LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING) | LOG_MASK(LOG_NOTICE); opterr = 1; while ((ch = getopt(ac, av, "I:vxl:nq:o:P:M:m:t:")) != EOF) { switch (ch) { case 'I': { in_addr_t ipAddr = inet_addr(optarg); if ((in_addr_t) -1 == ipAddr) { (void) fprintf(stderr, "Interface specification \"%s\" " "isn't an IP address\n", optarg); exit(1); } locIpAddr = ipAddr; break; } case 'v': logmask |= LOG_MASK(LOG_INFO); break; case 'x': logmask |= LOG_MASK(LOG_DEBUG); break; case 'l': logfname = optarg; break; case 'q': pqfname = optarg; setQueuePath(optarg); break; case 'o': toffset = atoi(optarg); if (toffset == 0 && *optarg != '0') { (void) fprintf(stderr, "%s: invalid offset %s\n", av[0], optarg); usage(av[0]); } break; case 'P': { char* suffix = ""; long port; errno = 0; port = strtol(optarg, &suffix, 0); if (0 != errno || 0 != *suffix || 0 >= port || 0xffff < port) { (void) fprintf(stderr, "%s: invalid port %s\n", av[0], optarg); usage(av[0]); } ldmPort = (unsigned) port; break; } case 'M': { int max = atoi(optarg); if (max < 0) { (void) fprintf(stderr, "%s: invalid maximum number of clients %s\n", av[0], optarg); usage(av[0]); } maxClients = max; break; } case 'm': max_latency = atoi(optarg); if (max_latency <= 0) { (void) fprintf(stderr, "%s: invalid max_latency %s\n", av[0], optarg); usage(av[0]); } break; case 'n': doSomething = 0; break; case 't': rpctimeo = (unsigned) atoi(optarg); if (rpctimeo == 0 || rpctimeo > 32767) { (void) fprintf(stderr, "%s: invalid timeout %s", av[0], optarg); usage(av[0]); } break; case '?': usage(av[0]); break; } /* "switch" statement */ } /* argument loop */ if (ac - optind == 1) setLdmdConfigPath(av[optind]); (void) setulogmask(logmask); if (toffset != TOFFSET_NONE && toffset > max_latency) { (void) fprintf(stderr, "%s: invalid toffset (%d) > max_latency (%d)\n", av[0], toffset, max_latency); usage(av[0]); } } /* command-line argument decoding */ #ifndef DONTFORK /* * daemon behavior * * Background the process unless we are logging to stderr, in which * case we assume interactive. */ if (logfname == NULL || *logfname != '-') { /* detach */ pid_t pid; pid = ldmfork(); if (pid == -1) { log_add("Couldn't fork LDM daemon"); log_log(LOG_ERR); exit(2); } if (pid > 0) { /* parent */ (void) printf("%ld\n", (long) pid); exit(0); } /* detach the child from parents process group ?? */ (void) setsid(); } #endif /* * Initialize logger. * (Close fd 2 to remap stderr to the logfile, when * appropriate. I know, this is anal.) */ if (logfname == NULL ) (void) fclose(stderr); else if (!(logfname[0] == '-' && logfname[1] == 0)) (void) close(2); (void) openulog(ubasename(av[0]), (LOG_CONS | LOG_PID), LOG_LDM, logfname); unotice("Starting Up (version: %s; built: %s %s)", PACKAGE_VERSION, __DATE__, __TIME__); /* * register exit handler */ if (atexit(cleanup) != 0) { serror("atexit"); unotice("Exiting"); exit(1); } /* * set up signal handlers */ set_sigactions(); /* * Close the standard input and standard output streams because they won't * be used (more anality :-) */ (void) fclose(stdout); (void) fclose(stdin); if (!doSomething) { /* * Vet the configuration file. */ udebug("main(): Vetting configuration-file"); if (read_conf(getLdmdConfigPath(), doSomething, ldmPort) != 0) { log_log(LOG_ERR); exit(1); } } else { /* * Create a service portal. This should be done before anything is * created because this is the function that relinquishes superuser * privileges. */ udebug("main(): Creating service portal"); if (create_ldm_tcp_svc(&sock, locIpAddr, ldmPort) != ENOERR) { /* error reports are emitted from create_ldm_tcp_svc() */ exit(1); } udebug("tcp sock: %d", sock); /* * Verify that the product-queue can be open for writing. */ udebug("main(): Opening product-queue"); if (status = pq_open(pqfname, PQ_DEFAULT, &pq)) { if (PQ_CORRUPT == status) { uerror("The product-queue \"%s\" is inconsistent", pqfname); } else { uerror("pq_open failed: %s: %s", pqfname, strerror(status)); } exit(1); } (void) pq_close(pq); pq = NULL; /* * Create the sharable database of upstream LDM metadata. */ udebug("main(): Creating shared upstream LDM database"); if (status = uldb_delete(NULL)) { if (ULDB_EXIST == status) { log_clear(); } else { LOG_ADD0( "Couldn't delete existing shared upstream LDM database"); log_log(LOG_ERR); exit(1); } } if (uldb_create(NULL, maxClients * 1024)) { LOG_ADD0("Couldn't create shared upstream LDM database"); log_log(LOG_ERR); exit(1); } /* * Read the configuration file (downstream LDM-s are started). */ udebug("main(): Reading configuration-file"); if (read_conf(getLdmdConfigPath(), doSomething, ldmPort) != 0) { log_log(LOG_ERR); exit(1); } /* * Serve */ udebug("main(): Serving socket"); sock_svc(sock); } /* "doSomething" is true */ return (0); }
int main(int argc, char** argv){ CONFIG cfg; cfg_init(&cfg); //read commandline args if(!arg_parse(&cfg, argc-1, argv+1)){ return -1; } //read config file if(!cfg.cfg_file){ fprintf(stderr, "No config file supplied\n"); return -1; } if(!cfg_read(&cfg, cfg.cfg_file)){ cfg_free(&cfg); return -1; } //if not using pgpass, ask for database password if(!cfg.db.use_pgpass){ cfg.db.pass=calloc(sizeof(char),MAX_PASSWORD_LENGTH+1); if(!cfg.db.pass){ fprintf(stderr, "Failed to allocate memory\n"); cfg_free(&cfg); return -1; } fprintf(stderr, "DB Password: "******"\fWaiting..."); ask_password(cfg.db.pass, MAX_PASSWORD_LENGTH); } //check for sane config if(!cfg_sane(&cfg)){ cfg_free(&cfg); return -1; } //connect to database if persistent if(cfg.db.persist_connection){ if(!pq_connect(&(cfg.db))){ cfg_free(&cfg); return -1; } if(cfg.verbosity>2){ fprintf(stderr, "Database connection established\n"); } } //connect to remote devices if(!comms_open(&cfg)){ comms_close(&cfg); pq_close(&(cfg.db)); cfg_free(&cfg); return -1; } //set up signal handlers signal(SIGINT, sig_interrupt); signal(SIGTERM, sig_terminate); //run the state machine garfield_pos(&cfg); comms_close(&cfg); pq_close(&(cfg.db)); cfg_free(&cfg); return 0; }
/** * @retval LDM7_INVAL No multicast sender child process exists. */ static int sender_terminate(void) { int retval = 0; int status; #if CANCEL_SENDER udebug("Canceling sender thread"); status = pthread_cancel(sender.thread); if (status) { LOG_ERRNUM0(status, "Couldn't cancel sender thread"); retval = status; } #else udebug("Writing to termination pipe"); status = write(sender.fds[1], &status, sizeof(int)); if (status == -1) { LOG_SERROR0("Couldn't write to termination pipe"); retval = status; } #endif void* statusPtr; udebug("Joining sender thread"); status = pthread_join(sender.thread, &statusPtr); if (status) { LOG_ERRNUM0(status, "Couldn't join sender thread"); retval = status; } if (statusPtr != PTHREAD_CANCELED) { status = *(int*)statusPtr; if (status) { LOG_START1("Sender task exit-status was %d", status); retval = status; } } (void)close(sender.sock); udebug("Terminating multicast sender"); status = terminateMcastSender(); if (status) { LOG_ADD0("Couldn't terminate multicast sender process"); retval = status; } udebug("Clearing multicast LDM sender manager"); status = mlsm_clear(); if (status) { LOG_ADD0("mlsm_clear() failure"); retval = status; } status = pq_close(pq); if (status) { LOG_ADD0("pq_close() failure"); retval = status; } status = deleteProductQueue(UP7_PQ_PATHNAME); if (status) { LOG_ADD0("deleteProductQueue() failure"); retval = status; } return retval; }
/*ARGSUSED*/ static int exec_prodput( const product* prod, int argc, char** argv, const void* xprod, size_t xlen) { pid_t pid = 0; if (NULL == execMap) { execMap = cm_new(); if (NULL == execMap) { LOG_ADD0("Couldn't create child-process map for EXEC entries"); log_log(LOG_ERR); pid = -1; } } /* child-process map not allocated */ if (0 == pid) { int waitOnChild = 0; /* default is not to wait */ if (strcmp(argv[0], "-wait") == 0) { waitOnChild = 1; /* => wait for child */ argc--; argv++; } pid = ldmfork(); if (-1 == pid) { LOG_SERROR0("Couldn't fork EXEC process"); log_log(LOG_ERR); } else { if (0 == pid) { /* * Child process. * * Detach the child process from the parents process group?? * * (void) setpgid(0,0); */ const unsigned ulogOptions = ulog_get_options(); const char* ulogIdent = getulogident(); const unsigned ulogFacility = getulogfacility(); const char* ulogPath = getulogpath(); (void)signal(SIGTERM, SIG_DFL); (void)pq_close(pq); /* * It is assumed that the standard input, output, and error * streams are correctly established and should not be * modified. */ /* * Don't let the child process get any inappropriate privileges. */ endpriv(); (void) execvp(argv[0], argv); openulog(ulogIdent, ulogOptions, ulogFacility, ulogPath); LOG_SERROR1("Couldn't execute command \"%s\"", argv[0]); log_log(LOG_ERR); exit(EXIT_FAILURE); } /* child process */ else { /* * Parent process. */ (void)cm_add_argv(execMap, pid, argv); if (!waitOnChild) { udebug(" exec %s[%d]", argv[0], pid); } else { udebug(" exec -wait %s[%d]", argv[0], pid); (void)reap(pid, 0); } } } /* child-process forked */ } /* child-process map allocated */ return -1 == pid ? -1 : 1; }
/* * Called at exit. * This callback routine registered by atexit(). */ static void cleanup( void) { const char* const pqfname = getQueuePath(); unotice("Exiting"); lcf_savePreviousProdInfo(); free_remote_clss(); /* * Ensure release of COMINGSOON-reserved space in product-queue. */ clr_pip_5(); down6_destroy(); /* * Close product-queue. */ if (pq) { (void) pq_close(pq); pq = NULL; } /* * Ensure that this process has no entry in the upstream LDM database and * that the database is closed. */ (void) uldb_remove(getpid()); (void) uldb_close(); log_clear(); if (getpid() == getpgrp()) { /* * This process is the process group leader (i.e., the top-level * LDM server). */ if (portIsMapped) { int vers; /* * Superuser privileges might be required to unmap the * port on which the LDM is listening. */ rootpriv(); for (vers = MIN_LDM_VERSION; vers <= MAX_LDM_VERSION; vers++) { if (!pmap_unset(LDMPROG, vers)) uerror("pmap_unset(LDMPROG %lu, LDMVERS %lu) " "failed", LDMPROG, vers); else portIsMapped = 0; } unpriv(); } /* * Terminate all child processes. */ { /* * Ignore the signal I'm about to send my process group. */ struct sigaction sigact; (void) sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigact.sa_handler = SIG_IGN; (void) sigaction(SIGTERM, &sigact, NULL ); } /* * Signal my process group. */ unotice("Terminating process group"); (void) kill(0, SIGTERM); while (reap(-1, 0) > 0) ; /*empty*/ /* * Delete the upstream LDM database. */ (void) uldb_delete(NULL); #if WANT_MULTICAST /* * Destroy the multicast LDM sender map. */ msm_destroy(); #endif } /* * Free access-control-list resources. */ lcf_free(); /* * Close registry. */ if (reg_close()) log_log(LOG_ERR); /* * Terminate logging. */ (void) closeulog(); }
int main( int ac, char* av[]) { const char* pqfname = getQueuePath(); int status; int doSomething = 1; in_addr_t ldmIpAddr = (in_addr_t) htonl(INADDR_ANY ); unsigned ldmPort = LDM_PORT; ensureDumpable(); /* * deal with the command line, set options */ { extern int optind; extern int opterr; extern char *optarg; int ch; int logmask = LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING) | LOG_MASK(LOG_NOTICE); opterr = 1; while ((ch = getopt(ac, av, "I:vxl:nq:o:P:M:m:t:")) != EOF) { switch (ch) { case 'I': { in_addr_t ipAddr = inet_addr(optarg); if ((in_addr_t) -1 == ipAddr) { (void) fprintf(stderr, "Interface specification \"%s\" " "isn't an IP address\n", optarg); exit(1); } ldmIpAddr = ipAddr; break; } case 'v': logmask |= LOG_MASK(LOG_INFO); break; case 'x': logmask |= LOG_MASK(LOG_DEBUG); break; case 'l': logfname = optarg; break; case 'q': pqfname = optarg; setQueuePath(optarg); break; case 'o': toffset = atoi(optarg); if (toffset == 0 && *optarg != '0') { (void) fprintf(stderr, "%s: invalid offset %s\n", av[0], optarg); usage(av[0]); } break; case 'P': { unsigned port; int nbytes; if (sscanf(optarg, "%5u %n", &port, &nbytes) != 1 || 0 != optarg[nbytes] || port > 0xffff) { (void)fprintf(stderr, "%s: invalid port number: %s\n", av[0], optarg); usage(av[0]); } ldmPort = port; break; } case 'M': { int max = atoi(optarg); if (max < 0) { (void) fprintf(stderr, "%s: invalid maximum number of clients %s\n", av[0], optarg); usage(av[0]); } maxClients = max; break; } case 'm': max_latency = atoi(optarg); if (max_latency <= 0) { (void) fprintf(stderr, "%s: invalid max_latency %s\n", av[0], optarg); usage(av[0]); } break; case 'n': doSomething = 0; break; case 't': rpctimeo = (unsigned) atoi(optarg); if (rpctimeo == 0 || rpctimeo > 32767) { (void) fprintf(stderr, "%s: invalid timeout %s", av[0], optarg); usage(av[0]); } break; case '?': usage(av[0]); break; } /* "switch" statement */ } /* argument loop */ if (ac - optind == 1) setLdmdConfigPath(av[optind]); (void) setulogmask(logmask); if (toffset != TOFFSET_NONE && toffset > max_latency) { (void) fprintf(stderr, "%s: invalid toffset (%d) > max_latency (%d)\n", av[0], toffset, max_latency); usage(av[0]); } } /* command-line argument decoding */ if (logfname != NULL && *logfname == '-') { /* * Logging to standard error stream. Assume interactive. * * Make this process a process group leader so that all child processes * (e.g., upstream LDM, downstream LDM, pqact(1)s) will be signaled by * `cleanup()`. */ (void)setpgid(0, 0); // can't fail } #ifndef DONTFORK else { /* * Logging to system logging daemon or file. Make this process a daemon. */ pid_t pid; pid = ldmfork(); if (pid == -1) { log_add("Couldn't fork LDM daemon"); log_log(LOG_ERR); exit(2); } if (pid > 0) { /* parent */ (void) printf("%ld\n", (long) pid); exit(0); } /* detach the child from parents process group ?? */ (void) setsid(); // also makes this process a process group leader } #endif /* * Initialize logger. * (Close fd 2 to remap stderr to the logfile, when * appropriate. I know, this is anal.) */ if (logfname == NULL ) (void) fclose(stderr); else if (!(logfname[0] == '-' && logfname[1] == 0)) (void) close(2); (void) openulog(ubasename(av[0]), (LOG_CONS | LOG_PID), LOG_LDM, logfname); unotice("Starting Up (version: %s; built: %s %s)", PACKAGE_VERSION, __DATE__, __TIME__); /* * register exit handler */ if (atexit(cleanup) != 0) { serror("atexit"); unotice("Exiting"); exit(1); } /* * set up signal handlers */ set_sigactions(); /* * Close the standard input and standard output streams because they won't * be used (more anality :-) */ (void) fclose(stdout); (void) fclose(stdin); /* * Vet the configuration file. */ udebug("main(): Vetting configuration-file"); if (read_conf(getLdmdConfigPath(), 0, ldmIpAddr, ldmPort) != 0) { log_log(LOG_ERR); exit(1); } if (doSomething) { int sock = -1; if (lcf_isServerNeeded()) { /* * Create a service portal. This should be done before anything is * created because this is the function that relinquishes superuser * privileges. */ udebug("main(): Creating service portal"); if (create_ldm_tcp_svc(&sock, ldmIpAddr, ldmPort) != ENOERR) { /* error reports are emitted from create_ldm_tcp_svc() */ exit(1); } udebug("tcp sock: %d", sock); } /* * Verify that the product-queue can be open for writing. */ udebug("main(): Opening product-queue"); if ((status = pq_open(pqfname, PQ_DEFAULT, &pq))) { if (PQ_CORRUPT == status) { uerror("The product-queue \"%s\" is inconsistent", pqfname); } else { uerror("pq_open failed: %s: %s", pqfname, strerror(status)); } exit(1); } (void) pq_close(pq); pq = NULL; /* * Create the sharable database of upstream LDM metadata. */ udebug("main(): Creating shared upstream LDM database"); if ((status = uldb_delete(NULL))) { if (ULDB_EXIST == status) { log_clear(); } else { LOG_ADD0( "Couldn't delete existing shared upstream LDM database"); log_log(LOG_ERR); exit(1); } } if (uldb_create(NULL, maxClients * 1024)) { LOG_ADD0("Couldn't create shared upstream LDM database"); log_log(LOG_ERR); exit(1); } /* * Initialize the multicast sender map. */ #if WANT_MULTICAST if (msm_init()) { LOG_ADD0("Couldn't initialize multicast LDM sender map"); log_log(LOG_ERR); exit(1); } #endif /* * Re-read (and execute) the configuration file (downstream LDM-s are * started). */ lcf_free(); // Start with a clean slate to prevent duplicates udebug("main(): Reading configuration-file"); if (read_conf(getLdmdConfigPath(), 1, ldmIpAddr, ldmPort) != 0) { log_log(LOG_ERR); exit(1); } if (lcf_isServerNeeded()) { /* * Serve */ udebug("main(): Serving socket"); sock_svc(sock); } else { /* * Wait until all child processes have terminated. */ while (reap(-1, 0) > 0) /* empty */; } } // configuration-file will be executed return (0); }
/*----------------------------------------*/ int main(int argc, char **argv) { int rc; int ssmcr_tries=0; infolog_SetFacility("CTP"); infolog_SetStream("",0); #ifdef PQWAY printf("main_ctp: opening rec/send queues...\n"); mq_rec= pq_open(); if(mq_rec==(mqd_t)-1) { infolog_trgboth(LOG_FATAL, "posix mq_rec not created"); exit(8); } mq_sendmsg= pq_connect(); if(mq_sendmsg==(mqd_t)-1) { infolog_trgboth(LOG_FATAL, "posix mq_sendmsg not connected"); exit(8); } #endif signal(SIGUSR1, gotsignal); siginterrupt(SIGUSR1, 0); signal(SIGQUIT, gotsignal); siginterrupt(SIGQUIT, 0); signal(SIGKILL, gotsignal); siginterrupt(SIGKILL, 0); // -9 signal(SIGTERM, gotsignal); siginterrupt(SIGTERM, 0); // kill pid signal(SIGINT, gotsignal); siginterrupt(SIGINT, 0); // CTRL C 2 partmode[0]='\0'; printf("cshmInit i.e. initBakery(swtriggers/ccread/ssmcr ONLY once, when shm allocated)...\n"); /*printf("initBakery(swtriggers,4): 0:SOD/EOD 1:gcalib 2:ctp.exe 3:dims\n"); printf("initBakery(ccread,5): 0:proxy 1:dims 2:ctp+busytool 3:smaq 4:inputs\n"); */ cshmInit(); setglobalflags(argc, argv); /* changed in aug2016 (initBakery only once from now, when shm allocated) printf("initBakery(swtriggers,4): 0:SOD/EOD 1:gcalib 2:ctp.exe 3:dims\n"); initBakery(&ctpshmbase->swtriggers, "swtriggers", swtriggers_N); printf("initBakery(ccread,6): 0:proxy 1:dims 2:ctp+busytool 3:smaq 4:inputs 5:orbitddl2\n"); initBakery(&ctpshmbase->ccread, "ccread", ccread_N); printf("initBakery(ssmcr,4): 0:smaq 1:orbitddl2 2:ctp 3:inputs\n"); initBakery(&ctpshmbase->ssmcr, "ssmcr", ssmcr_N); */ printBakery(&ctpshmbase->swtriggers); printBakery(&ctpshmbase->ccread); printBakery(&ctpshmbase->ssmcr); unlockBakery(&ctpshmbase->swtriggers,swtriggers_ctpproxy); unlockBakery(&ctpshmbase->ccread,ccread_ctpproxy); unlockBakery(&ctpshmbase->ssmcr,ssmcr_ctpproxy); /* Let' synchronise with smcr only, i.e. - ccread_dims,... can go in parallel with ctp_Initproxy, orbitddl2: should use ccread_orbitddl2 customer when reading counters - swtriggers_gcalib/_dims cannot appear (no global runs becasue ctpproxy being restarted) */ while(1) { // do not allow SSM usage (smaq) because ctp_Initproxy is initialising it char msg[100]; rc= lockBakeryTimeout(&ctpshmbase->ssmcr,ssmcr_ctpproxy, 10); if(rc==1) { if(ssmcr_tries>0) { sprintf(msg, "Got ssmcr resource after %d attempts", ssmcr_tries); infolog_trgboth(LOG_INFO, msg); }; break; // ssmcr reserved for me now }; ssmcr_tries++; sprintf(msg,"%d secs Waiting for ssmcr resource. Is smaq stopped?", ssmcr_tries*10); infolog_trgboth(LOG_WARNING, msg); }; if(isArg(argc, argv, "configrunset")) { /* do we need before orbitddl2.py INT/L2 orbit in SYNC (automatic with L2a)? */ int rc, reslen; char cmd[200]; char result[1000]=""; // ~ 10 lines char orbchanged[]="Warning: orbitoffset changed:"; if(envcmp("VMESITE", "PRIVATE")==0) { strcpy(cmd, "who"); } else { strcpy(cmd, "orbitddl2.py configrunset"); }; infolog_trgboth(LOG_INFO, "Starting L0 orbit calibration (30s...)"); rc= popenread(cmd, result, 1000); // opens vme... reslen= strlen(result); if((rc==EXIT_FAILURE) || (reslen<=1)) { infolog_trgboth(LOG_ERROR, "L0 orbit calibration problem"); } else { int ixr= reslen; if(result[ixr-1]=='\n') { //remove last NL character if present result[ixr-1]='\0'; ixr= reslen-2; } else { ixr= reslen-1; // pointer to the last non-NEWLINE character }; while(ixr>=0) { // find last line if(result[ixr]=='\n') { ixr++; break; }; ixr--; }; sprintf(cmd, "L0 orbit calibration: %s", &result[ixr]); if((strcmp(&result[ixr], "Everything ok")==0) || (strncmp(&result[ixr], orbchanged, strlen(orbchanged))==0) ) { infolog_trgboth(LOG_INFO, cmd); } else { infolog_trgboth(LOG_ERROR, cmd); infolog_trgboth(LOG_ERROR, "ctpproxy not started"); unlockBakery(&ctpshmbase->ssmcr,ssmcr_ctpproxy); rc=8; goto STP; }; }; }; // init CTP after calibration (e.g. to repair modifications done by orbitddl2.py) rc=ctp_Initproxy(); unlockBakery(&ctpshmbase->ssmcr,ssmcr_ctpproxy); if(rc!=0) goto STP; // DIM services not registered here (see ctpdims.c), they run in separae task: // ds_register(); strcpy(obj,argv[1]); smi_attach(obj, SMI_handle_command); printf("CTP attached to: %s\n",obj); /* if smi_volatile: stops the ctp_proxy in case TRIGGER domain is down smi_volatile(); */ strcpy(errorReason,"not set"); smi_set_parER(); strcpy(ORBIT_NUMBER,""); smi_set_par("ORBIT_NUMBER",ORBIT_NUMBER,STRING); smi_setState("RUNNING"); while(1) { #ifdef PQWAY executectp("wait"); #else usleep(1000000); #endif if(quit>9) break; }; rc= ctp_Endproxy(); STP: #ifdef PQWAY pq_close(mq_sendmsg, 0); pq_close(mq_rec, 1); #endif printf("Calling cshmDetach()...\n"); cshmDetach(); return (rc); }