void LLThread::start() { apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp); // We won't bother joining apr_thread_detach(mAPRThreadp); }
void LLThread::start() { llassert(isStopped()); // Set thread state to running mStatus = RUNNING; apr_status_t status = apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool()); if(status == APR_SUCCESS) { // We won't bother joining apr_thread_detach(mAPRThreadp); } else { mStatus = STOPPED; llwarns << "failed to start thread " << mName << llendl; ll_apr_warn_status(status); } }
/* * The worker thread function. Take a task from the queue and perform it if * there is any. Otherwise, put itself into the idle thread list and waiting * for signal to wake up. * The thread terminate directly by detach and exit when it is asked to stop * after finishing a task. Otherwise, the thread should be in idle thread list * and should be joined. */ static void *APR_THREAD_FUNC thread_pool_func(apr_thread_t * t, void *param) { apr_thread_pool_t *me = param; apr_thread_pool_task_t *task = NULL; apr_interval_time_t wait; struct apr_thread_list_elt *elt; apr_thread_mutex_lock(me->lock); --me->spawning_cnt; elt = elt_new(me, t); if (!elt) { apr_thread_mutex_unlock(me->lock); apr_thread_exit(t, APR_ENOMEM); } while (!me->terminated && elt->state != TH_STOP) { /* Test if not new element, it is awakened from idle */ if (APR_RING_NEXT(elt, link) != elt) { --me->idle_cnt; APR_RING_REMOVE(elt, link); } APR_RING_INSERT_TAIL(me->busy_thds, elt, apr_thread_list_elt, link); task = pop_task(me); while (NULL != task && !me->terminated) { ++me->tasks_run; elt->current_owner = task->owner; apr_thread_mutex_unlock(me->lock); apr_thread_data_set(task, "apr_thread_pool_task", NULL, t); task->func(t, task->param); apr_thread_mutex_lock(me->lock); APR_RING_INSERT_TAIL(me->recycled_tasks, task, apr_thread_pool_task, link); elt->current_owner = NULL; if (TH_STOP == elt->state) { break; } task = pop_task(me); } assert(NULL == elt->current_owner); if (TH_STOP != elt->state) APR_RING_REMOVE(elt, link); /* Test if a busy thread been asked to stop, which is not joinable */ if ((me->idle_cnt >= me->idle_max && !(me->scheduled_task_cnt && 0 >= me->idle_max) && !me->idle_wait) || me->terminated || elt->state != TH_RUN) { --me->thd_cnt; if ((TH_PROBATION == elt->state) && me->idle_wait) ++me->thd_timed_out; APR_RING_INSERT_TAIL(me->recycled_thds, elt, apr_thread_list_elt, link); apr_thread_mutex_unlock(me->lock); apr_thread_detach(t); apr_thread_exit(t, APR_SUCCESS); return NULL; /* should not be here, safe net */ } /* busy thread become idle */ ++me->idle_cnt; APR_RING_INSERT_TAIL(me->idle_thds, elt, apr_thread_list_elt, link); /* * If there is a scheduled task, always scheduled to perform that task. * Since there is no guarantee that current idle threads are scheduled * for next scheduled task. */ if (me->scheduled_task_cnt) wait = waiting_time(me); else if (me->idle_cnt > me->idle_max) { wait = me->idle_wait; elt->state = TH_PROBATION; } else wait = -1; if (wait >= 0) { apr_thread_cond_timedwait(me->cond, me->lock, wait); } else { apr_thread_cond_wait(me->cond, me->lock); } } /* idle thread been asked to stop, will be joined */ --me->thd_cnt; apr_thread_mutex_unlock(me->lock); apr_thread_exit(t, APR_SUCCESS); return NULL; /* should not be here, safe net */ }
/*--------------------------------------------------------------------------*/ static int post_config_hook(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { apr_status_t rv; const char *pk = "advertise_init_module_tag"; apr_pool_t *pproc = s->process->pool; apr_thread_t *tp; mod_advertise_config *mconf = ap_get_module_config(s->module_config, &advertise_module); int advertisefound = 0; server_rec *server = s; /* Advertise directive in more than one VirtualHost: not supported */ while (server) { mod_advertise_config *conf = ap_get_module_config(server->module_config, &advertise_module); if (conf->ma_advertise_server == server) { if (advertisefound) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_advertise: directive in more than one VirtualHost: not supported"); return !OK; } else advertisefound = -1; } server = server->next; } /* Our server */ server = s; while (server) { mconf = ap_get_module_config(server->module_config, &advertise_module); if (mconf->ma_advertise_server == server) break; server = server->next; } apr_pool_userdata_get((void *)&magd, pk, pproc); if (!magd) { if (!(magd = apr_pcalloc(pproc, sizeof(ma_global_data_t)))) return apr_get_os_error(); apr_pool_create(&magd->ppool, pproc); apr_pool_userdata_set(magd, pk, apr_pool_cleanup_null, pproc); /* First time config phase -- skip. */ return OK; } #if defined(WIN32) { const char *ppid = getenv("AP_PARENT_PID"); if (ppid) { ma_parent_pid = atol(ppid); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "[%" APR_PID_T_FMT " - %" APR_PID_T_FMT "] in child post config hook", getpid(), ma_parent_pid); return OK; } } #endif ma_server_rec = server; if (mconf->ma_advertise_skey) { apr_md5_ctx_t mc; apr_md5_init(&mc); apr_md5_update(&mc, mconf->ma_advertise_skey, strlen(mconf->ma_advertise_skey)); apr_md5_final(magd->ssalt, &mc); } else { /* If security key is not configured, the digest is calculated from zero bytes */ memset(magd->ssalt, '\0', APR_MD5_DIGESTSIZE); } apr_uuid_get(&magd->suuid); magd->srvid[0] = '/'; apr_uuid_format(&magd->srvid[1], &magd->suuid); if (!mconf->ma_advertise_srvh) mconf->ma_advertise_srvh = magd->srvid; /* Check if we have advertise set */ if (mconf->ma_advertise_mode != ma_advertise_off && mconf->ma_advertise_adrs) { rv = ma_group_join(mconf->ma_advertise_adrs, mconf->ma_advertise_port, mconf->ma_bind_adrs, mconf->ma_bind_port, pconf, s); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "mod_advertise: multicast join failed for %s:%d.", mconf->ma_advertise_adrs, mconf->ma_advertise_port); ma_advertise_run = 0; } else { ma_advertise_run = 1; ma_advertise_stat = 200; } } /* Fill default values */ if (!mconf->ma_advertise_srvm) { if (ma_server_rec && ma_server_rec->server_scheme) { /* ServerName scheme://fully-qualified-domain-name[:port] */ mconf->ma_advertise_srvm = apr_pstrdup(pconf, ma_server_rec->server_scheme); } else { mconf->ma_advertise_srvm = apr_pstrdup(pconf, "http"); } } if (mconf->ma_advertise_srvs == NULL && ma_server_rec) { /* * That is not easy just use ServerAdvertise with the server parameter * if the code below doesn't work */ char *ptr = NULL; int port = DEFAULT_HTTP_PORT; if (ma_server_rec->addrs && ma_server_rec->addrs->host_addr && ma_server_rec->addrs->host_addr->next == NULL) { ptr = apr_psprintf(pproc, "%pI", ma_server_rec->addrs->host_addr); } /* Use don't use any as local address too */ if (ptr == NULL || strncmp(ptr,"0.0.0.0", 7) == 0 || strncmp(ptr,"::",2) == 0) { if ( ma_server_rec->port == 0 || ma_server_rec->port == 1) { if (ma_server_rec->addrs->host_addr->port != 0) port = ma_server_rec->addrs->host_addr->port; } else { port = ma_server_rec->port; } ptr = apr_psprintf(pproc, "%s:%lu", ma_server_rec->server_hostname, port); } rv = apr_parse_addr_port(&mconf->ma_advertise_srvs, &mconf->ma_advertise_srvi, &mconf->ma_advertise_srvp, ptr, pproc); if (rv != APR_SUCCESS || !mconf->ma_advertise_srvs || !mconf->ma_advertise_srvp) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, "mod_advertise: Invalid ServerAdvertise Address %s", ptr); return rv; } } /* prevent X-Manager-Address: (null):0 */ if (!mconf->ma_advertise_srvs || !mconf->ma_advertise_srvp) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "mod_advertise: ServerAdvertise Address or Port not defined, Advertise disabled!!!"); return OK; } /* Create parent management thread */ is_mp_running = 1; rv = apr_thread_create(&tp, NULL, parent_thread, server, pconf); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, "mod_advertise: parent apr_thread_create"); return rv; } apr_thread_detach(tp); /* Create cleanup pool that will be destroyed first * in future use new apr_pool_pre_cleanup_register from APR 1.3 */ apr_pool_create(&magd->cpool, pconf); apr_pool_cleanup_register(magd->cpool, magd, pconfig_cleanup, apr_pool_cleanup_null); ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, "Advertise initialized for process %" APR_PID_T_FMT, getpid()); apr_pool_cleanup_register(magd->ppool, magd, process_cleanup, apr_pool_cleanup_null); return OK; }