op_generic_t *gop_timed_waitany(op_generic_t *g, int dt) { op_generic_t *gop = NULL; apr_interval_time_t adt = apr_time_from_sec(dt); int loop; lock_gop(g); _gop_start_execution(g); //** Make sure things have been submitted loop = 0; if (gop_get_type(g) == Q_TYPE_QUE) { while (((gop = (op_generic_t *)pop(g->q->finished)) == NULL) && (g->q->nleft > 0) && (loop == 0)) { apr_thread_cond_timedwait(g->base.ctl->cond, g->base.ctl->lock, adt); //** Sleep until something completes loop++; } } else { while ((g->base.state == 0) && (loop == 0)) { apr_thread_cond_timedwait(g->base.ctl->cond, g->base.ctl->lock, adt); //** Sleep until something completes loop++; } if (g->base.state != 0) gop = g; } unlock_gop(g); return(gop); }
int gop_timed_waitall(op_generic_t *g, int dt) { int status; int loop; apr_interval_time_t adt = apr_time_from_sec(dt); lock_gop(g); _gop_start_execution(g); //** Make sure things have been submitted loop = 0; if (gop_get_type(g) == Q_TYPE_QUE) { while ((g->q->nleft > 0) && (loop == 0)) { apr_thread_cond_timedwait(g->base.ctl->cond, g->base.ctl->lock, adt); //** Sleep until something completes loop++; } status = (g->q->nleft > 0) ? OP_STATE_RETRY : _gop_completed_successfully(g); } else { while ((g->base.state == 0) && (loop == 0)) { apr_thread_cond_timedwait(g->base.ctl->cond, g->base.ctl->lock, adt); //** Sleep until something completes loop++; } status = (g->base.state == 0) ? OP_STATE_RETRY : _gop_completed_successfully(g); } unlock_gop(g); return(status); }
apr_status_t h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait) { apr_status_t status; workers_unregister(m); status = apr_thread_mutex_lock(m->lock); if (APR_SUCCESS == status) { int attempts = 0; release(m); while (apr_atomic_read32(&m->refs) > 0) { m->join_wait = wait; ap_log_cerror(APLOG_MARK, (attempts? APLOG_INFO : APLOG_DEBUG), 0, m->c, "h2_mplx(%ld): release_join, refs=%d, waiting...", m->id, m->refs); apr_thread_cond_timedwait(wait, m->lock, apr_time_from_sec(10)); if (++attempts >= 6) { ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, APLOGNO(02952) "h2_mplx(%ld): join attempts exhausted, refs=%d", m->id, m->refs); break; } } if (m->join_wait) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c, "h2_mplx(%ld): release_join -> destroy", m->id); } m->join_wait = NULL; apr_thread_mutex_unlock(m->lock); h2_mplx_destroy(m); } return status; }
apr_status_t h2_mplx_out_trywait(h2_mplx *m, apr_interval_time_t timeout, apr_thread_cond_t *iowait) { apr_status_t status; int acquired; AP_DEBUG_ASSERT(m); if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) { if (m->aborted) { status = APR_ECONNABORTED; } else { m->added_output = iowait; status = apr_thread_cond_timedwait(m->added_output, m->lock, timeout); if (APLOGctrace2(m->c)) { ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c, "h2_mplx(%ld): trywait on data for %f ms)", m->id, timeout/1000.0); } m->added_output = NULL; } leave_mutex(m, acquired); } return status; }
ASR_CLIENT_DECLARE(const char*) asr_session_wait_for_termination( asr_session_t *asr_session) { const mrcp_app_message_t *app_message = NULL; mrcp_message_t *mrcp_message = NULL; /* Wait for events either START-OF-INPUT or RECOGNITION-COMPLETE */ do { apr_thread_mutex_lock(asr_session->mutex); app_message = NULL; if(apr_thread_cond_timedwait(asr_session->wait_object,asr_session->mutex, 60 * 1000000) != APR_SUCCESS) { apr_thread_mutex_unlock(asr_session->mutex); return NULL; } app_message = asr_session->app_message; asr_session->app_message = NULL; apr_thread_mutex_unlock(asr_session->mutex); mrcp_message = mrcp_event_get(app_message); if(mrcp_message && mrcp_message->start_line.method_id == RECOGNIZER_RECOGNITION_COMPLETE) { asr_session->recog_complete = mrcp_message; } } while(!asr_session->recog_complete); /* Get results */ return nlsml_input_get(asr_session->recog_complete); }
static void dynamic_binding(abts_case *tc, void *data) { unsigned int i; apr_status_t rv; toolbox_t box[NTHREADS]; apr_thread_t *thread[NTHREADS]; apr_thread_mutex_t *mutex[NTHREADS]; apr_thread_cond_t *cond = NULL; rv = apr_thread_cond_create(&cond, p); ABTS_SUCCESS(rv); ABTS_PTR_NOTNULL(tc, cond); for (i = 0; i < NTHREADS; i++) { rv = apr_thread_mutex_create(&mutex[i], APR_THREAD_MUTEX_DEFAULT, p); ABTS_SUCCESS(rv); rv = apr_thread_mutex_lock(mutex[i]); ABTS_SUCCESS(rv); box[i].tc = tc; box[i].cond = cond; box[i].mutex = mutex[i]; box[i].func = lock_and_signal; rv = apr_thread_create(&thread[i], NULL, thread_routine, &box[i], p); ABTS_SUCCESS(rv); } /* * The dynamic binding should be preserved because we use only one waiter */ for (i = 0; i < NTHREADS; i++) { rv = apr_thread_cond_wait(cond, mutex[i]); ABTS_SUCCESS(rv); } for (i = 0; i < NTHREADS; i++) { rv = apr_thread_cond_timedwait(cond, mutex[i], 10000); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); rv = apr_thread_mutex_unlock(mutex[i]); ABTS_SUCCESS(rv); } for (i = 0; i < NTHREADS; i++) { apr_status_t retval; rv = apr_thread_join(&retval, thread[i]); ABTS_SUCCESS(rv); } rv = apr_thread_cond_destroy(cond); ABTS_SUCCESS(rv); for (i = 0; i < NTHREADS; i++) { rv = apr_thread_mutex_destroy(mutex[i]); ABTS_SUCCESS(rv); } }
/** * Push new data onto the queue. Blocks if the queue is full. Once * the push operation has completed, it signals other threads waiting * in apr_queue_pop() that they may continue consuming sockets. * @param timeout added by Cisco. now uses apr_thread_cond_timewait(). * interval of time to wait. zero means forever, negative indicates no wait, * otherwise wait time in *microseconds*. * @return APR_SUCCESS, APR_EAGAIN, APR_EOF, APR_EINTR, APR_TIMEUP, * or some APR error */ apr_status_t etch_apr_queue_push(etch_apr_queue_t *queue, apr_interval_time_t timeout, void *data) { apr_status_t rv; if (queue->terminated) rv = APR_EOF; /* no more elements ever again */ else if (APR_SUCCESS == (rv = apr_thread_mutex_lock(queue->one_big_mutex))) { do { if (etch_apr_queue_full(queue)) { if (!queue->terminated) { if (-1 == timeout) { rv = APR_EAGAIN; /* asked to not wait */ break; } queue->full_waiters++; if (0 == timeout) rv = apr_thread_cond_wait(queue->not_full, queue->one_big_mutex); else rv = apr_thread_cond_timedwait(queue->not_full, queue->one_big_mutex, timeout); queue->full_waiters--; if (rv != APR_SUCCESS) break; } /* If we wake up and it's still empty, then we were interrupted */ if (etch_apr_queue_full(queue)) { Q_DBG("queue full (intr)", queue); rv = queue->terminated? APR_EOF: APR_EINTR; break; } } queue->data[queue->in] = data; queue->in = (queue->in + 1) % queue->bounds; queue->nelts++; if (queue->empty_waiters) { Q_DBG("sig !empty", queue); rv = apr_thread_cond_signal(queue->not_empty); } } while(0); apr_thread_mutex_unlock(queue->one_big_mutex); } return rv; }
static apr_status_t wait_cond(h2_bucket_beam *beam, apr_thread_mutex_t *lock) { if (beam->timeout > 0) { return apr_thread_cond_timedwait(beam->m_cond, lock, beam->timeout); } else { return apr_thread_cond_wait(beam->m_cond, lock); } }
void hportal_wait(host_portal_t *hp, int dt) { apr_time_t t; if (dt < 0) return; //** If negative time has run out so return tbx_ns_timeout_set(&t, dt, 0); apr_thread_cond_timedwait(hp->cond, hp->lock, t); }
/* Stop SPEAK/RECOGNIZE request on speech channel. */ int speech_channel_stop(speech_channel_t *schannel) { int status = 0; if (schannel == NULL) return -1; if (schannel->mutex != NULL) apr_thread_mutex_lock(schannel->mutex); if (schannel->state == SPEECH_CHANNEL_PROCESSING) { mrcp_method_id method; mrcp_message_t *mrcp_message; if (schannel->type == SPEECH_CHANNEL_SYNTHESIZER) method = SYNTHESIZER_STOP; else method = RECOGNIZER_STOP; ast_log(LOG_DEBUG, "(%s) Stopping %s\n", schannel->name, speech_channel_type_to_string(schannel->type)); /* Send STOP to MRCP server. */ mrcp_message = mrcp_application_message_create(schannel->unimrcp_session, schannel->unimrcp_channel, method); if (mrcp_message == NULL) { ast_log(LOG_ERROR, "(%s) Failed to create STOP message\n", schannel->name); status = -1; } else { if (!mrcp_application_message_send(schannel->unimrcp_session, schannel->unimrcp_channel, mrcp_message)) ast_log(LOG_WARNING, "(%s) Failed to send STOP message\n", schannel->name); else if (schannel->cond != NULL) { while (schannel->state == SPEECH_CHANNEL_PROCESSING) { if (apr_thread_cond_timedwait(schannel->cond, schannel->mutex, SPEECH_CHANNEL_TIMEOUT_USEC) == APR_TIMEUP) { break; } } } if (schannel->state == SPEECH_CHANNEL_PROCESSING) { ast_log(LOG_ERROR, "(%s) Timed out waiting for session to close. Continuing\n", schannel->name); schannel->state = SPEECH_CHANNEL_ERROR; status = -1; } else if (schannel->state == SPEECH_CHANNEL_ERROR) { ast_log(LOG_ERROR, "(%s) Channel error\n", schannel->name); schannel->state = SPEECH_CHANNEL_ERROR; status = -1; } else { ast_log(LOG_DEBUG, "(%s) %s stopped\n", schannel->name, speech_channel_type_to_string(schannel->type)); } } } if (schannel->mutex != NULL) apr_thread_mutex_unlock(schannel->mutex); return status; }
static void lost_signal(abts_case *tc, void *data) { apr_status_t rv; apr_thread_cond_t *cond = NULL; apr_thread_mutex_t *mutex = NULL; rv = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, p); ABTS_SUCCESS(rv); ABTS_PTR_NOTNULL(tc, mutex); rv = apr_thread_cond_create(&cond, p); ABTS_SUCCESS(rv); ABTS_PTR_NOTNULL(tc, cond); rv = apr_thread_cond_signal(cond); ABTS_SUCCESS(rv); rv = apr_thread_mutex_lock(mutex); ABTS_SUCCESS(rv); rv = apr_thread_cond_timedwait(cond, mutex, 10000); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); rv = apr_thread_mutex_unlock(mutex); ABTS_SUCCESS(rv); rv = apr_thread_cond_broadcast(cond); ABTS_SUCCESS(rv); rv = apr_thread_mutex_lock(mutex); ABTS_SUCCESS(rv); rv = apr_thread_cond_timedwait(cond, mutex, 10000); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); rv = apr_thread_mutex_unlock(mutex); ABTS_SUCCESS(rv); rv = apr_thread_cond_destroy(cond); ABTS_SUCCESS(rv); rv = apr_thread_mutex_destroy(mutex); ABTS_SUCCESS(rv); }
SWITCH_DECLARE(switch_status_t) switch_thread_cond_timedwait(switch_thread_cond_t *cond, switch_mutex_t *mutex, switch_interval_time_t timeout) { apr_status_t st = apr_thread_cond_timedwait(cond, mutex, timeout); if (st == APR_TIMEUP) { st = SWITCH_STATUS_TIMEOUT; } return st; }
APU_DECLARE(apr_status_t) apr_reslist_acquire(apr_reslist_t *reslist, void **resource) { apr_status_t rv; apr_res_t *res; apr_thread_mutex_lock(reslist->listlock); /* If there are idle resources on the available list, use * them right away. */ if (reslist->nidle > 0) { /* Pop off the first resource */ res = pop_resource(reslist); *resource = res->opaque; free_container(reslist, res); apr_thread_mutex_unlock(reslist->listlock); return APR_SUCCESS; } /* If we've hit our max, block until we're allowed to create * a new one, or something becomes free. */ else while (reslist->ntotal >= reslist->hmax && reslist->nidle <= 0) { if (reslist->timeout) { if ((rv = apr_thread_cond_timedwait(reslist->avail, reslist->listlock, reslist->timeout)) != APR_SUCCESS) { apr_thread_mutex_unlock(reslist->listlock); return rv; } } else apr_thread_cond_wait(reslist->avail, reslist->listlock); } /* If we popped out of the loop, first try to see if there * are new resources available for immediate use. */ if (reslist->nidle > 0) { res = pop_resource(reslist); *resource = res->opaque; free_container(reslist, res); apr_thread_mutex_unlock(reslist->listlock); return APR_SUCCESS; } /* Otherwise the reason we dropped out of the loop * was because there is a new slot available, so create * a resource to fill the slot and use it. */ else { rv = create_resource(reslist, &res); if (rv == APR_SUCCESS) { reslist->ntotal++; *resource = res->opaque; } free_container(reslist, res); apr_thread_mutex_unlock(reslist->listlock); return rv; } }
apr_status_t h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait) { apr_status_t status; int acquired; h2_workers_unregister(m->workers, m); if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) { int i, wait_secs = 5; /* disable WINDOW_UPDATE callbacks */ h2_mplx_set_consumed_cb(m, NULL, NULL); while (!h2_io_set_iter(m->stream_ios, stream_done_iter, m)) { /* iterate until all ios have been orphaned or destroyed */ } /* Any remaining ios have handed out requests to workers that are * not done yet. Any operation they do on their assigned stream ios will * be errored ECONNRESET/ABORTED, so that should find out pretty soon. */ for (i = 0; h2_io_set_size(m->stream_ios) > 0; ++i) { m->join_wait = wait; ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c, "h2_mplx(%ld): release_join, waiting on %d worker to report back", m->id, (int)h2_io_set_size(m->stream_ios)); status = apr_thread_cond_timedwait(wait, m->lock, apr_time_from_sec(wait_secs)); if (APR_STATUS_IS_TIMEUP(status)) { if (i > 0) { /* Oh, oh. Still we wait for assigned workers to report that * they are done. Unless we have a bug, a worker seems to be hanging. * If we exit now, all will be deallocated and the worker, once * it does return, will walk all over freed memory... */ ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, "h2_mplx(%ld): release, waiting for %d seconds now for " "all h2_workers to return, have still %d requests outstanding", m->id, i*wait_secs, (int)h2_io_set_size(m->stream_ios)); } } } ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c, "h2_mplx(%ld): release_join -> destroy", m->id); leave_mutex(m, acquired); h2_mplx_destroy(m); /* all gone */ } return status; }
/** \brief Send MRCP request to client stack and wait for async response */ static apt_bool_t uni_recog_mrcp_request_send(uni_speech_t *uni_speech, mrcp_message_t *message) { apt_bool_t res = FALSE; apr_thread_mutex_lock(uni_speech->mutex); uni_speech->mrcp_request = message; /* Send MRCP request */ ast_log(LOG_DEBUG, "(%s) Send MRCP request method-id: %d\n",uni_speech->name,(int)message->start_line.method_id); res = mrcp_application_message_send(uni_speech->session,uni_speech->channel,message); if(res == TRUE) { /* Wait for MRCP response */ ast_log(LOG_DEBUG, "(%s) Wait for MRCP response\n",uni_speech->name); if(apr_thread_cond_timedwait(uni_speech->wait_object,uni_speech->mutex,MRCP_APP_REQUEST_TIMEOUT) != APR_SUCCESS) { ast_log(LOG_ERROR, "(%s) Failed to get MRCP response: request timed out\n",uni_speech->name); uni_speech->mrcp_response = NULL; } /* Wake up and check received response */ if(uni_speech->mrcp_response) { mrcp_message_t *mrcp_response = uni_speech->mrcp_response; ast_log(LOG_DEBUG, "(%s) Process MRCP response method-id: %d status-code: %d\n", uni_speech->name, (int)mrcp_response->start_line.method_id, mrcp_response->start_line.status_code); if(mrcp_response->start_line.status_code != MRCP_STATUS_CODE_SUCCESS && mrcp_response->start_line.status_code != MRCP_STATUS_CODE_SUCCESS_WITH_IGNORE) { ast_log(LOG_WARNING, "(%s) MRCP request failed method-id: %d status-code: %d\n", uni_speech->name, (int)mrcp_response->start_line.method_id, mrcp_response->start_line.status_code); res = FALSE; } } else { ast_log(LOG_ERROR, "(%s) No MRCP response available\n",uni_speech->name); res = FALSE; } } else { ast_log(LOG_WARNING, "(%s) Failed to send MRCP request\n",uni_speech->name); } uni_speech->mrcp_request = NULL; apr_thread_mutex_unlock(uni_speech->mutex); return res; }
/* Read from the audio queue. */ apr_status_t audio_queue_read(audio_queue_t *queue, void *data, apr_size_t *data_len, int block) { apr_size_t requested; int status = 0; if ((queue == NULL) || (data == NULL) || (data_len == NULL)) return -1; else requested = *data_len; if (queue->mutex != NULL) apr_thread_mutex_lock(queue->mutex); /* Wait for data, if allowed. */ if (block != 0) { if (audio_buffer_inuse(queue->buffer) < requested) { queue->waiting = requested; if ((queue->mutex != NULL) && (queue->cond != NULL)) apr_thread_cond_timedwait(queue->cond, queue->mutex, AUDIO_QUEUE_READ_TIMEOUT_USEC); } queue->waiting = 0; } if (audio_buffer_inuse(queue->buffer) < requested) requested = audio_buffer_inuse(queue->buffer); if (requested == 0) { *data_len = 0; status = -1; } else { /* Read the data. */ *data_len = audio_buffer_read(queue->buffer, data, requested); queue->read_bytes = queue->read_bytes + *data_len; } if (queue->mutex != NULL) apr_thread_mutex_unlock(queue->mutex); return status; }
void *ds_ibp_warm_thread(apr_thread_t *th, void *data) { data_service_fn_t *dsf = (data_service_fn_t *)data; ds_ibp_priv_t *ds = (ds_ibp_priv_t *)dsf->priv; apr_time_t max_wait; char *mcap; apr_ssize_t hlen; apr_hash_index_t *hi; ibp_capset_t *w; opque_t *q; int dt, err; dt = 60; max_wait = apr_time_make(ds->warm_interval, 0); apr_thread_mutex_lock(ds->lock); while (ds->warm_stop == 0) { //** Generate all the tasks log_printf(10, "Starting auto-warming run\n"); q = new_opque(); for (hi=apr_hash_first(NULL, ds->warm_table); hi != NULL; hi = apr_hash_next(hi)) { apr_hash_this(hi, (const void **)&mcap, &hlen, (void **)&w); opque_add(q, new_ibp_modify_alloc_op(ds->ic, mcap, -1, ds->warm_duration, -1, dt)); log_printf(15, " warming: %s\n", mcap); } //** Wait until they all complete err = opque_waitall(q); log_printf(10, "opque_waitall=%d\n", err); opque_free(q, OP_DESTROY); //** Clean up. Don;t care if we are successfull or not:) //** Sleep until the next time or we get an exit request apr_thread_cond_timedwait(ds->cond, ds->lock, max_wait); } apr_thread_mutex_unlock(ds->lock); log_printf(10, "EXITING auto-warm thread\n"); return(NULL); }
/** \brief Send session management request to client stack and wait for async response */ static apt_bool_t uni_recog_sm_request_send(uni_speech_t *uni_speech, mrcp_sig_command_e sm_request) { apt_bool_t res = FALSE; ast_log(LOG_DEBUG, "Send session request type:%d\n",sm_request); apr_thread_mutex_lock(uni_speech->mutex); uni_speech->is_sm_request = TRUE; uni_speech->sm_request = sm_request; switch(sm_request) { case MRCP_SIG_COMMAND_SESSION_UPDATE: res = mrcp_application_session_update(uni_speech->session); break; case MRCP_SIG_COMMAND_SESSION_TERMINATE: res = mrcp_application_session_terminate(uni_speech->session); break; case MRCP_SIG_COMMAND_CHANNEL_ADD: res = mrcp_application_channel_add(uni_speech->session,uni_speech->channel); break; case MRCP_SIG_COMMAND_CHANNEL_REMOVE: res = mrcp_application_channel_remove(uni_speech->session,uni_speech->channel); break; case MRCP_SIG_COMMAND_RESOURCE_DISCOVER: res = mrcp_application_resource_discover(uni_speech->session); break; default: break; } if(res == TRUE) { /* Wait for session response */ ast_log(LOG_DEBUG, "Wait for session response\n"); if(apr_thread_cond_timedwait(uni_speech->wait_object,uni_speech->mutex,MRCP_APP_REQUEST_TIMEOUT) != APR_SUCCESS) { ast_log(LOG_ERROR, "Failed to get response, request timed out\n"); uni_speech->sm_response = MRCP_SIG_STATUS_CODE_FAILURE; } ast_log(LOG_DEBUG, "Waked up, status code: %d\n",uni_speech->sm_response); } uni_speech->is_sm_request = FALSE; apr_thread_mutex_unlock(uni_speech->mutex); return res; }
apr_status_t h2_mplx_out_trywait(h2_mplx *m, apr_interval_time_t timeout, apr_thread_cond_t *iowait) { AP_DEBUG_ASSERT(m); if (m->aborted) { return APR_ECONNABORTED; } apr_status_t status = apr_thread_mutex_lock(m->lock); if (APR_SUCCESS == status) { m->added_output = iowait; status = apr_thread_cond_timedwait(m->added_output, m->lock, timeout); if (APLOGctrace2(m->c)) { ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, m->c, "h2_mplx(%ld): trywait on data for %f ms)", m->id, timeout/1000.0); } m->added_output = NULL; apr_thread_mutex_unlock(m->lock); } return status; }
void *rss_check_thread(apr_thread_t *th, void *data) { resource_service_fn_t *rs = (resource_service_fn_t *)data; rs_simple_priv_t *rss = (rs_simple_priv_t *)rs->priv; int do_notify, map_version, status_change; apr_interval_time_t dt; dt = apr_time_from_sec(rss->check_interval); apr_thread_mutex_lock(rss->lock); rss->current_check = 0; //** Triggers a reload do { log_printf(5, "LOOP START\n"); _rs_simple_refresh(rs); //** Do a quick check and see if the file has changed do_notify = 0; if (rss->current_check != rss->modify_time) { //** Need to reload rss->current_check = rss->modify_time; do_notify = 1; // _rss_make_check_table(rs); } map_version = rss->modify_time; apr_thread_mutex_unlock(rss->lock); status_change = (rss->check_timeout <= 0) ? 0 : rss_perform_check(rs); if (((do_notify == 1) && (rss->dynamic_mapping == 1)) || (status_change != 0)) rss_mapping_notify(rs, map_version, status_change); log_printf(5, "LOOP END\n"); apr_thread_mutex_lock(rss->lock); if (rss->shutdown == 0) apr_thread_cond_timedwait(rss->cond, rss->lock, dt); } while (rss->shutdown == 0); //** Clean up _rss_clear_check_table(rss->ds, rss->rid_mapping, rss->mpool); apr_thread_mutex_unlock(rss->lock); return(NULL); }
static void nested_lock_and_unlock(toolbox_t *box) { apr_status_t rv; abts_case *tc = box->tc; rv = apr_thread_mutex_lock(box->mutex); ABTS_SUCCESS(rv); rv = apr_thread_mutex_lock(box->mutex); ABTS_SUCCESS(rv); rv = apr_thread_mutex_lock(box->mutex); ABTS_SUCCESS(rv); rv = apr_thread_cond_timedwait(box->cond, box->mutex, 2000000); ABTS_SUCCESS(rv); rv = apr_thread_mutex_unlock(box->mutex); ABTS_SUCCESS(rv); rv = apr_thread_mutex_unlock(box->mutex); ABTS_SUCCESS(rv); }
/** \brief Send MRCP request to client stack and wait for async response */ static apt_bool_t uni_recog_mrcp_request_send(uni_speech_t *uni_speech, mrcp_message_t *message) { apt_bool_t res = FALSE; apr_thread_mutex_lock(uni_speech->mutex); uni_speech->mrcp_request = message; /* Send MRCP request */ ast_log(LOG_DEBUG, "Send MRCP request\n"); res = mrcp_application_message_send(uni_speech->session,uni_speech->channel,message); if(res == TRUE) { /* Wait for MRCP response */ ast_log(LOG_DEBUG, "Wait for MRCP response\n"); if(apr_thread_cond_timedwait(uni_speech->wait_object,uni_speech->mutex,MRCP_APP_REQUEST_TIMEOUT) != APR_SUCCESS) { ast_log(LOG_ERROR, "Failed to get response, request timed out\n"); uni_speech->mrcp_response = NULL; } ast_log(LOG_DEBUG, "Waked up\n"); } uni_speech->mrcp_request = NULL; apr_thread_mutex_unlock(uni_speech->mutex); return res; }
static void test_timeoutcond(abts_case *tc, void *data) { apr_status_t s; apr_interval_time_t timeout; apr_time_t begin, end; int i; s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, s); ABTS_PTR_NOTNULL(tc, timeout_mutex); s = apr_thread_cond_create(&timeout_cond, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, s); ABTS_PTR_NOTNULL(tc, timeout_cond); timeout = apr_time_from_sec(5); for (i = 0; i < MAX_RETRY; i++) { apr_thread_mutex_lock(timeout_mutex); begin = apr_time_now(); s = apr_thread_cond_timedwait(timeout_cond, timeout_mutex, timeout); end = apr_time_now(); apr_thread_mutex_unlock(timeout_mutex); if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) { continue; } ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s)); ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 500000); break; } ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY); APR_ASSERT_SUCCESS(tc, "Unable to destroy the conditional", apr_thread_cond_destroy(timeout_cond)); }
void *ongoing_heartbeat_thread(apr_thread_t *th, void *data) { mq_ongoing_t *on = (mq_ongoing_t *)data; apr_time_t timeout = apr_time_make(on->check_interval, 0); op_generic_t *gop; mq_msg_t *msg; ongoing_hb_t *oh; ongoing_table_t *table; apr_hash_index_t *hi, *hit; opque_t *q; char *id; mq_msg_hash_t *remote_hash; apr_time_t now; apr_ssize_t id_len; int n, k; char *remote_host_string; apr_thread_mutex_lock(on->lock); n = 0; do { now = apr_time_now() - apr_time_from_sec(5); //** Give our selves a little buffer log_printf(5, "Loop Start now=" TT "\n", apr_time_now()); q = new_opque(); // opque_start_execution(q); for (hit = apr_hash_first(NULL, on->table); hit != NULL; hit = apr_hash_next(hit)) { apr_hash_this(hit, (const void **)&remote_hash, &id_len, (void **)&table); k = apr_hash_count(table->table); if (log_level() > 1) { remote_host_string = mq_address_to_string(table->remote_host); log_printf(1, "host=%s count=%d\n", remote_host_string, k); free(remote_host_string); } for (hi = apr_hash_first(NULL, table->table); hi != NULL; hi = apr_hash_next(hi)) { apr_hash_this(hi, (const void **)&id, &id_len, (void **)&oh); log_printf(1, "id=%s now=" TT " next_check=" TT "\n", oh->id, apr_time_sec(apr_time_now()), apr_time_sec(oh->next_check)); if (now > oh->next_check) { log_printf(1, "id=%s sending HEARTBEAT EXEC SUBMIT nows=" TT " hb=%d\n", oh->id, apr_time_sec(apr_time_now()), oh->heartbeat); flush_log(); //** Form the message msg = mq_make_exec_core_msg(table->remote_host, 1); mq_msg_append_mem(msg, ONGOING_KEY, ONGOING_SIZE, MQF_MSG_KEEP_DATA); mq_msg_append_mem(msg, oh->id, oh->id_len, MQF_MSG_KEEP_DATA); mq_msg_append_mem(msg, NULL, 0, MQF_MSG_KEEP_DATA); //** Make the gop gop = new_mq_op(on->mqc, msg, ongoing_response_status, NULL, NULL, oh->heartbeat); gop_set_private(gop, table); opque_add(q, gop); oh->in_progress = 1; //** Flag it as in progress so it doesn't get deleted behind the scenes } } } log_printf(5, "Loop end now=" TT "\n", apr_time_now()); //** Wait for it to complete apr_thread_mutex_unlock(on->lock); opque_waitall(q); apr_thread_mutex_lock(on->lock); //** Dec the counters while ((gop = opque_waitany(q)) != NULL) { log_printf(0, "gid=%d gotone status=%d now=" TT "\n", gop_id(gop), (gop_get_status(gop)).op_status, apr_time_sec(apr_time_now())); table = gop_get_private(gop); table->count--; //** Update the next check for (hi = apr_hash_first(NULL, table->table); hi != NULL; hi = apr_hash_next(hi)) { apr_hash_this(hi, (const void **)&id, &id_len, (void **)&oh); oh->next_check = apr_time_now() + apr_time_from_sec(oh->heartbeat); //** Check if we get rid of it oh->in_progress = 0; if (oh->count <= 0) { //** Need to delete it apr_hash_set(table->table, id, id_len, NULL); free(oh->id); free(oh); } } gop_free(gop, OP_DESTROY); } opque_free(q, OP_DESTROY); now = apr_time_now(); log_printf(2, "sleeping %d now=" TT "\n", on->check_interval, now); //** Sleep until time for the next heartbeat or time to exit if (on->shutdown == 0) apr_thread_cond_timedwait(on->cond, on->lock, timeout); n = on->shutdown; now = apr_time_now() - now; log_printf(2, "main loop bottom n=%d dt=" TT " sec=" TT "\n", n, now, apr_time_sec(now)); } while (n == 0); log_printf(2, "CLEANUP\n"); for (hit = apr_hash_first(NULL, on->table); hit != NULL; hit = apr_hash_next(hit)) { apr_hash_this(hit, (const void **)&remote_hash, &id_len, (void **)&table); for (hi = apr_hash_first(NULL, table->table); hi != NULL; hi = apr_hash_next(hi)) { apr_hash_this(hi, (const void **)&id, &id_len, (void **)&oh); apr_hash_set(table->table, id, id_len, NULL); free(oh->id); free(oh); } apr_hash_set(on->table, &(table->remote_host_hash), sizeof(mq_msg_hash_t), NULL); mq_msg_destroy(table->remote_host); free(table); } log_printf(2, "EXITING\n"); apr_thread_mutex_unlock(on->lock); return(NULL); }
/* Send SPEAK request to synthesizer. */ static int synth_channel_speak(speech_channel_t *schannel, const char *content, const char *content_type, apr_hash_t *header_fields) { int status = 0; mrcp_message_t *mrcp_message = NULL; mrcp_generic_header_t *generic_header = NULL; mrcp_synth_header_t *synth_header = NULL; if (!schannel || !content || !content_type) { ast_log(LOG_ERROR, "synth_channel_speak: unknown channel error!\n"); return -1; } apr_thread_mutex_lock(schannel->mutex); if (schannel->state != SPEECH_CHANNEL_READY) { apr_thread_mutex_unlock(schannel->mutex); return -1; } if ((mrcp_message = mrcp_application_message_create(schannel->unimrcp_session, schannel->unimrcp_channel, SYNTHESIZER_SPEAK)) == NULL) { ast_log(LOG_ERROR, "(%s) Failed to create SPEAK message\n", schannel->name); apr_thread_mutex_unlock(schannel->mutex); return -1; } /* Set generic header fields (content-type). */ if ((generic_header = (mrcp_generic_header_t *)mrcp_generic_header_prepare(mrcp_message)) == NULL) { apr_thread_mutex_unlock(schannel->mutex); return -1; } apt_string_assign(&generic_header->content_type, content_type, mrcp_message->pool); mrcp_generic_header_property_add(mrcp_message, GENERIC_HEADER_CONTENT_TYPE); /* Set synthesizer header fields (voice, rate, etc.). */ if ((synth_header = (mrcp_synth_header_t *)mrcp_resource_header_prepare(mrcp_message)) == NULL) { apr_thread_mutex_unlock(schannel->mutex); return -1; } /* Add params to MRCP message. */ speech_channel_set_params(schannel, mrcp_message, header_fields); /* Set body (plain text or SSML). */ apt_string_assign(&mrcp_message->body, content, schannel->pool); /* Empty audio queue and send SPEAK to MRCP server. */ audio_queue_clear(schannel->audio_queue); if (!mrcp_application_message_send(schannel->unimrcp_session, schannel->unimrcp_channel, mrcp_message)) { ast_log(LOG_ERROR,"(%s) Failed to send SPEAK message", schannel->name); apr_thread_mutex_unlock(schannel->mutex); return -1; } /* Wait for IN PROGRESS. */ apr_thread_cond_timedwait(schannel->cond, schannel->mutex, SPEECH_CHANNEL_TIMEOUT_USEC); if (schannel->state != SPEECH_CHANNEL_PROCESSING) { apr_thread_mutex_unlock(schannel->mutex); return -1; } apr_thread_mutex_unlock(schannel->mutex); return status; }
/** * Retrieves the next item from the queue. If there are no * items available, it will block until one becomes available. * Once retrieved, the item is placed into the address specified by * 'data'. * @param timeout added by Cisco. now uses apr_thread_cond_timewait(). * interval of time to wait. zero means forever, -1 means no wait, * -2 means don't wait and ignore queue closed indicator, * otherwise timeout is blocking time in microseconds. * @return APR_SUCCESS, APR_EAGAIN, APR_EOF, APR_EINTR, APR_TIMEUP, * or some APR error */ apr_status_t etch_apr_queue_pop(etch_apr_queue_t *queue, apr_interval_time_t timeout, void **data) { apr_status_t rv; if (queue->terminated) /* Cisco back door to clear closed queue */ { if (timeout != ETCHQUEUE_CLEARING_CLOSED_QUEUE) return APR_EOF; /* no more elements ever again */ } if (APR_SUCCESS == (rv = apr_thread_mutex_lock(queue->one_big_mutex))) { do { /* Keep waiting until we wake up and find that the queue is not empty. */ if (etch_apr_queue_empty(queue)) { if (-1 == timeout) { rv = APR_EAGAIN; /* asked to not wait */ break; } if (!queue->terminated) { queue->empty_waiters++; if (0 == timeout) rv = apr_thread_cond_wait(queue->not_empty, queue->one_big_mutex); else rv = apr_thread_cond_timedwait(queue->not_empty, queue->one_big_mutex, timeout); queue->empty_waiters--; if (rv != APR_SUCCESS) /* rv will be APR_TIMEUP if timed out */ break; } /* If we wake up and it's still empty, then we were interrupted */ if (etch_apr_queue_empty(queue)) { Q_DBG("queue empty (intr)", queue); rv = queue->terminated? APR_EOF: APR_EINTR; break; } } *data = queue->data[queue->out]; queue->nelts--; queue->out = (queue->out + 1) % queue->bounds; if (queue->full_waiters) { Q_DBG("signal !full", queue); rv = apr_thread_cond_signal(queue->not_full); } } while(0); apr_thread_mutex_unlock(queue->one_big_mutex); } return rv; }
/** Initiate recognition based on specified grammar and input stream */ ASR_CLIENT_DECLARE(const char*) asr_session_stream_recognize( asr_session_t *asr_session, const char *grammar_file) { const mrcp_app_message_t *app_message; mrcp_message_t *mrcp_message; app_message = NULL; mrcp_message = define_grammar_message_create(asr_session,grammar_file); if(!mrcp_message) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create DEFINE-GRAMMAR Request"); return NULL; } /* Send DEFINE-GRAMMAR request and wait for the response */ apr_thread_mutex_lock(asr_session->mutex); if(mrcp_application_message_send(asr_session->mrcp_session,asr_session->mrcp_channel,mrcp_message) == TRUE) { apr_thread_cond_wait(asr_session->wait_object,asr_session->mutex); app_message = asr_session->app_message; asr_session->app_message = NULL; } apr_thread_mutex_unlock(asr_session->mutex); if(mrcp_response_check(app_message,MRCP_REQUEST_STATE_COMPLETE) == FALSE) { return NULL; } /* Reset prev recog result (if any) */ asr_session->recog_complete = NULL; app_message = NULL; mrcp_message = recognize_message_create(asr_session); if(!mrcp_message) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create RECOGNIZE Request"); return NULL; } /* Send RECOGNIZE request and wait for the response */ apr_thread_mutex_lock(asr_session->mutex); if(mrcp_application_message_send(asr_session->mrcp_session,asr_session->mrcp_channel,mrcp_message) == TRUE) { apr_thread_cond_wait(asr_session->wait_object,asr_session->mutex); app_message = asr_session->app_message; asr_session->app_message = NULL; } apr_thread_mutex_unlock(asr_session->mutex); if(mrcp_response_check(app_message,MRCP_REQUEST_STATE_INPROGRESS) == FALSE) { return NULL; } /* Reset media buffer */ mpf_frame_buffer_restart(asr_session->media_buffer); /* Set input mode and start streaming */ asr_session->input_mode = INPUT_MODE_STREAM; asr_session->streaming = TRUE; /* Wait for events either START-OF-INPUT or RECOGNITION-COMPLETE */ do { apr_thread_mutex_lock(asr_session->mutex); app_message = NULL; if(apr_thread_cond_timedwait(asr_session->wait_object,asr_session->mutex, 60 * 1000000) != APR_SUCCESS) { apr_thread_mutex_unlock(asr_session->mutex); return NULL; } app_message = asr_session->app_message; asr_session->app_message = NULL; apr_thread_mutex_unlock(asr_session->mutex); mrcp_message = mrcp_event_get(app_message); if(mrcp_message && mrcp_message->start_line.method_id == RECOGNIZER_RECOGNITION_COMPLETE) { asr_session->recog_complete = mrcp_message; } } while(!asr_session->recog_complete); /* Get results */ return nlsml_input_get(asr_session->recog_complete); }
int mq_stream_read_wait(mq_stream_t *mqs) { int err = 0; apr_interval_time_t dt; op_status_t status; //** If 1st time make all the variables if (mqs->mpool == NULL) { apr_pool_create(&mqs->mpool, NULL); apr_thread_mutex_create(&(mqs->lock), APR_THREAD_MUTEX_DEFAULT, mqs->mpool); apr_thread_cond_create(&(mqs->cond), mqs->mpool); } dt = apr_time_from_sec(1); //** Flag the just processed gop to clean up apr_thread_mutex_lock(mqs->lock); log_printf(5, "START msid=%d waiting=%d processed=%d gop_processed=%p\n", mqs->msid, mqs->waiting, mqs->processed, mqs->gop_processed); if (mqs->gop_processed != NULL) mqs->processed = 1; apr_thread_cond_broadcast(mqs->cond); if (mqs->data) { if (mqs->data[MQS_STATE_INDEX] != MQS_MORE) err = 1; } apr_thread_mutex_unlock(mqs->lock); if (mqs->gop_processed != NULL) { gop_waitany(mqs->gop_processed); gop_free(mqs->gop_processed, OP_DESTROY); mqs->gop_processed = NULL; } if (err != 0) { log_printf(2, "ERROR no more data available!\n"); return(-1); } //** Now handle the waiting gop apr_thread_mutex_lock(mqs->lock); log_printf(5, "before loop msid=%d waiting=%d processed=%d\n", mqs->msid, mqs->waiting, mqs->processed); while (mqs->waiting == 1) { log_printf(5, "LOOP msid=%d waiting=%d processed=%d\n", mqs->msid, mqs->waiting, mqs->processed); if (gop_will_block(mqs->gop_waiting) == 0) { //** Oops! failed request status = gop_get_status(mqs->gop_waiting); log_printf(2, "msid=%d gid=%d status=%d\n", mqs->msid, gop_id(mqs->gop_waiting), status.op_status); if (status.op_status != OP_STATE_SUCCESS) { mqs->waiting = -3; err = 1; } else { apr_thread_cond_timedwait(mqs->cond, mqs->lock, dt); } } else { apr_thread_cond_timedwait(mqs->cond, mqs->lock, dt); } } if (mqs->waiting == 0) { //** Flag the receiver to accept the data mqs->waiting = -1; apr_thread_cond_broadcast(mqs->cond); //** Let the receiver know we're ready to accept the data //** Wait for the data to be accepted while (mqs->waiting != -2) { apr_thread_cond_wait(mqs->cond, mqs->lock); } } else if (mqs->waiting == -3) { //**error occured err = 1; } apr_thread_mutex_unlock(mqs->lock); //** Flip states mqs->gop_processed = mqs->gop_waiting; mqs->gop_waiting = NULL; //** This shouldn't get triggered but just in case lets throw an error. if ((mqs->gop_processed == NULL) && (mqs->data != NULL)) { if ((mqs->data[MQS_STATE_INDEX] == MQS_MORE) && (mqs->want_more == MQS_MORE)) { err = 3; log_printf(0, "ERROR: MQS gop processed=waiting=NULL want_more set!!!!!! err=%d\n", err); fprintf(stderr, "ERROR: MQS gop processed=waiting=NULL want_more set!!!!!! err=%d\n", err); } } //** Check if we need to fire off the next request if (mqs->data != NULL) { if ((mqs->data[MQS_STATE_INDEX] == MQS_MORE) && (mqs->want_more == MQS_MORE)) { mq_stream_read_request(mqs); } } log_printf(5, "err=%d\n", err); return(err); }
/* * 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 */ }
int main(int argc, char **argv) { int start_option, i, watch, summary, base; rs_mapping_notify_t notify, me; apr_time_t dt; char *config; //printf("argc=%d\n", argc); if (argc < 2) { printf("\n"); printf("lio_rs LIO_COMMON_OPTIONS [-w] [-b2 | -b10] [-s | -f]\n"); lio_print_options(stdout); printf(" -w - Watch for RID configuration changes. Press ^C to exit\n"); printf(" -b2 - Use powers of 2 for units(default)\n"); printf(" -b10 - Use powers of 10 for units\n"); printf(" -s - Print a RID space usage summary\n"); printf(" -f - Print the full RID configuration\n"); return(1); } lio_init(&argc, &argv); watch = 0; summary = 0; base = 1024; i=1; do { start_option = i; if (strcmp(argv[i], "-w") == 0) { //** Watch for any RID changes i++; watch = 1; } else if (strcmp(argv[i], "-s") == 0) { //** Print space summary instead of full conifg i++; summary = 1; } else if (strcmp(argv[i], "-b2") == 0) { //** base-2 units i++; base = 1024; } else if (strcmp(argv[i], "-b10") == 0) { //** base-10 units i++; base = 1000; } } while ((start_option < i) && (i<argc)); //** Make the APR stuff assert_result(apr_pool_create(&mpool, NULL), APR_SUCCESS); apr_thread_mutex_create(&lock, APR_THREAD_MUTEX_DEFAULT, mpool); apr_thread_cond_create(&cond, mpool); //if (watch == 1) { // printf("Sleeping for 60s\n"); fflush(stdout); // sleep(60); // printf("Woken up\n"); fflush(stdout); //} memset(¬ify, 0, sizeof(notify)); notify.lock = lock; notify.cond = cond; me = notify; me.map_version = 1; //** This triggers the initial load rs_register_mapping_updates(lio_gc->rs, ¬ify); dt = apr_time_from_sec(1); do { //** Check for an update apr_thread_mutex_lock(lock); if (watch == 1) apr_thread_cond_timedwait(notify.cond, notify.lock, dt); i = ((me.map_version != notify.map_version) || (me.status_version != notify.status_version)) ? 1 : 0; me = notify; apr_thread_mutex_unlock(lock); if (i != 0) { config = rs_get_rid_config(lio_gc->rs); printf("Map Version: %d Status Version: %d\n", me.map_version, me.status_version); printf("--------------------------------------------------------------------------------------------------\n"); if (config == NULL) { printf("ERROR NULL config!\n"); } else if (summary == 1) { print_rid_summary(config, base); } else { printf("%s", config); } printf("--------------------------------------------------------------------------------------------------\n"); if (config != NULL) free(config); } } while (watch == 1); info_printf(lio_ifd, 5, "BEFORE unregister\n"); tbx_info_flush(lio_ifd); rs_unregister_mapping_updates(lio_gc->rs, ¬ify); info_printf(lio_ifd, 5, "AFTER unregister\n"); tbx_info_flush(lio_ifd); //** Cleanup apr_pool_destroy(mpool); // info_printf(lio_ifd, 5, "AFTER shutdown\n"); tbx_info_flush(lio_ifd); lio_shutdown(); return(0); }