void *test_setup(void *dummy) { apr_pool_t *test_pool; apr_pool_create(&test_pool, NULL); apr_pool_abort_set(pool_abort_func, test_pool); return initTestCtx(test_pool); }
static apr_status_t htdbm_init(apr_pool_t **pool, htdbm_t **hdbm) { #if APR_CHARSET_EBCDIC apr_status_t rv; #endif apr_pool_create( pool, NULL); apr_pool_abort_set(abort_on_oom, *pool); apr_file_open_stderr(&errfile, *pool); apr_signal(SIGINT, (void (*)(int)) htdbm_interrupted); (*hdbm) = (htdbm_t *)apr_pcalloc(*pool, sizeof(htdbm_t)); (*hdbm)->ctx.pool = *pool; #if APR_CHARSET_EBCDIC rv = apr_xlate_open(&((*hdbm)->to_ascii), "ISO-8859-1", APR_DEFAULT_CHARSET, (*hdbm)->ctx.pool); if (rv) { fprintf(stderr, "apr_xlate_open(to ASCII)->%d\n", rv); return APR_EGENERAL; } rv = apr_SHA1InitEBCDIC((*hdbm)->to_ascii); if (rv) { fprintf(stderr, "apr_SHA1InitEBCDIC()->%d\n", rv); return APR_EGENERAL; } rv = apr_MD5InitEBCDIC((*hdbm)->to_ascii); if (rv) { fprintf(stderr, "apr_MD5InitEBCDIC()->%d\n", rv); return APR_EGENERAL; } #endif /*APR_CHARSET_EBCDIC*/ /* Set MD5 as default */ (*hdbm)->ctx.alg = ALG_APMD5; (*hdbm)->type = "default"; return APR_SUCCESS; }
/* * main */ int main(int argc, const char * const argv[]) { apr_off_t max; apr_time_t current, repeat, delay, previous; apr_status_t status; apr_pool_t *pool, *instance; apr_getopt_t *o; apr_finfo_t info; int retries, isdaemon, limit_found, intelligent, dowork; char opt; const char *arg; char *proxypath, *path; interrupted = 0; repeat = 0; isdaemon = 0; dryrun = 0; limit_found = 0; max = 0; verbose = 0; realclean = 0; benice = 0; deldirs = 0; intelligent = 0; previous = 0; /* avoid compiler warning */ proxypath = NULL; if (apr_app_initialize(&argc, &argv, NULL) != APR_SUCCESS) { return 1; } atexit(apr_terminate); if (argc) { shortname = apr_filepath_name_get(argv[0]); } if (apr_pool_create(&pool, NULL) != APR_SUCCESS) { return 1; } apr_pool_abort_set(oom, pool); apr_file_open_stderr(&errfile, pool); apr_signal(SIGINT, setterm); apr_signal(SIGTERM, setterm); apr_getopt_init(&o, pool, argc, argv); while (1) { status = apr_getopt(o, "iDnvrtd:l:L:p:", &opt, &arg); if (status == APR_EOF) { break; } else if (status != APR_SUCCESS) { usage(); } else { switch (opt) { case 'i': if (intelligent) { usage(); } intelligent = 1; break; case 'D': if (dryrun) { usage(); } dryrun = 1; break; case 'n': if (benice) { usage(); } benice = 1; break; case 't': if (deldirs) { usage(); } deldirs = 1; break; case 'v': if (verbose) { usage(); } verbose = 1; break; case 'r': if (realclean) { usage(); } realclean = 1; deldirs = 1; break; case 'd': if (isdaemon) { usage(); } isdaemon = 1; repeat = apr_atoi64(arg); repeat *= SECS_PER_MIN; repeat *= APR_USEC_PER_SEC; break; case 'l': if (limit_found) { usage(); } limit_found = 1; do { apr_status_t rv; char *end; rv = apr_strtoff(&max, arg, &end, 10); if (rv == APR_SUCCESS) { if ((*end == 'K' || *end == 'k') && !end[1]) { max *= KBYTE; } else if ((*end == 'M' || *end == 'm') && !end[1]) { max *= MBYTE; } else if ((*end == 'G' || *end == 'g') && !end[1]) { max *= GBYTE; } else if (*end && /* neither empty nor [Bb] */ ((*end != 'B' && *end != 'b') || end[1])) { rv = APR_EGENERAL; } } if (rv != APR_SUCCESS) { apr_file_printf(errfile, "Invalid limit: %s" APR_EOL_STR APR_EOL_STR, arg); usage(); } } while(0); break; case 'p': if (proxypath) { usage(); } proxypath = apr_pstrdup(pool, arg); if (apr_filepath_set(proxypath, pool) != APR_SUCCESS) { usage(); } break; } /* switch */ } /* else */ } /* while */ if (o->ind != argc) { usage(); } if (isdaemon && (repeat <= 0 || verbose || realclean || dryrun)) { usage(); } if (!isdaemon && intelligent) { usage(); } if (!proxypath || max <= 0) { usage(); } if (apr_filepath_get(&path, 0, pool) != APR_SUCCESS) { usage(); } baselen = strlen(path); #ifndef DEBUG if (isdaemon) { apr_file_close(errfile); apr_proc_detach(APR_PROC_DETACH_DAEMONIZE); } #endif do { apr_pool_create(&instance, pool); now = apr_time_now(); APR_RING_INIT(&root, _entry, link); delcount = 0; unsolicited = 0; dowork = 0; switch (intelligent) { case 0: dowork = 1; break; case 1: retries = STAT_ATTEMPTS; status = APR_SUCCESS; do { if (status != APR_SUCCESS) { apr_sleep(STAT_DELAY); } status = apr_stat(&info, path, APR_FINFO_MTIME, instance); } while (status != APR_SUCCESS && !interrupted && --retries); if (status == APR_SUCCESS) { previous = info.mtime; intelligent = 2; } dowork = 1; break; case 2: retries = STAT_ATTEMPTS; status = APR_SUCCESS; do { if (status != APR_SUCCESS) { apr_sleep(STAT_DELAY); } status = apr_stat(&info, path, APR_FINFO_MTIME, instance); } while (status != APR_SUCCESS && !interrupted && --retries); if (status == APR_SUCCESS) { if (previous != info.mtime) { dowork = 1; } previous = info.mtime; break; } intelligent = 1; dowork = 1; break; } if (dowork && !interrupted) { if (!process_dir(path, instance) && !interrupted) { purge(path, instance, max); } else if (!isdaemon && !interrupted) { apr_file_printf(errfile, "An error occurred, cache cleaning " "aborted." APR_EOL_STR); return 1; } if (intelligent && !interrupted) { retries = STAT_ATTEMPTS; status = APR_SUCCESS; do { if (status != APR_SUCCESS) { apr_sleep(STAT_DELAY); } status = apr_stat(&info, path, APR_FINFO_MTIME, instance); } while (status != APR_SUCCESS && !interrupted && --retries); if (status == APR_SUCCESS) { previous = info.mtime; intelligent = 2; } else { intelligent = 1; } } } apr_pool_destroy(instance); current = apr_time_now(); if (current < now) { delay = repeat; } else if (current - now >= repeat) { delay = repeat; } else { delay = now + repeat - current; } /* we can't sleep the whole delay time here apiece as this is racy * with respect to interrupt delivery - think about what happens * if we have tested for an interrupt, then get scheduled * before the apr_sleep() call and while waiting for the cpu * we do get an interrupt */ if (isdaemon) { while (delay && !interrupted) { if (delay > APR_USEC_PER_SEC) { apr_sleep(APR_USEC_PER_SEC); delay -= APR_USEC_PER_SEC; } else { apr_sleep(delay); delay = 0; } } } } while (isdaemon && !interrupted); if (!isdaemon && interrupted) { apr_file_printf(errfile, "Cache cleaning aborted due to user " "request." APR_EOL_STR); return 1; } return 0; }
conn_rec *h2_slave_create(conn_rec *master, int slave_id, apr_pool_t *parent) { apr_allocator_t *allocator; apr_status_t status; apr_pool_t *pool; conn_rec *c; void *cfg; module *mpm; ap_assert(master); ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, master, "h2_stream(%ld-%d): create slave", master->id, slave_id); /* We create a pool with its own allocator to be used for * processing a request. This is the only way to have the processing * independant of its parent pool in the sense that it can work in * another thread. Also, the new allocator needs its own mutex to * synchronize sub-pools. */ apr_allocator_create(&allocator); apr_allocator_max_free_set(allocator, ap_max_mem_free); status = apr_pool_create_ex(&pool, parent, NULL, allocator); if (status != APR_SUCCESS) { ap_log_cerror(APLOG_MARK, APLOG_ERR, status, master, APLOGNO(10004) "h2_session(%ld-%d): create slave pool", master->id, slave_id); return NULL; } apr_allocator_owner_set(allocator, pool); apr_pool_abort_set(abort_on_oom, pool); apr_pool_tag(pool, "h2_slave_conn"); c = (conn_rec *) apr_palloc(pool, sizeof(conn_rec)); if (c == NULL) { ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, master, APLOGNO(02913) "h2_session(%ld-%d): create slave", master->id, slave_id); apr_pool_destroy(pool); return NULL; } memcpy(c, master, sizeof(conn_rec)); c->master = master; c->pool = pool; c->conn_config = ap_create_conn_config(pool); c->notes = apr_table_make(pool, 5); c->input_filters = NULL; c->output_filters = NULL; c->keepalives = 0; #if AP_MODULE_MAGIC_AT_LEAST(20180903, 1) c->filter_conn_ctx = NULL; #endif c->bucket_alloc = apr_bucket_alloc_create(pool); #if !AP_MODULE_MAGIC_AT_LEAST(20180720, 1) c->data_in_input_filters = 0; c->data_in_output_filters = 0; #endif /* prevent mpm_event from making wrong assumptions about this connection, * like e.g. using its socket for an async read check. */ c->clogging_input_filters = 1; c->log = NULL; c->log_id = apr_psprintf(pool, "%ld-%d", master->id, slave_id); c->aborted = 0; /* We cannot install the master connection socket on the slaves, as * modules mess with timeouts/blocking of the socket, with * unwanted side effects to the master connection processing. * Fortunately, since we never use the slave socket, we can just install * a single, process-wide dummy and everyone is happy. */ ap_set_module_config(c->conn_config, &core_module, dummy_socket); /* TODO: these should be unique to this thread */ c->sbh = master->sbh; /* TODO: not all mpm modules have learned about slave connections yet. * copy their config from master to slave. */ if ((mpm = h2_conn_mpm_module()) != NULL) { cfg = ap_get_module_config(master->conn_config, mpm); ap_set_module_config(c->conn_config, mpm, cfg); } ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, "h2_slave(%s): created", c->log_id); return c; }