static void shutdown_data_dtor(void *data) { struct shutdown_data *shutdown_data = data; ast_mutex_destroy(&shutdown_data->lock); ast_cond_destroy(&shutdown_data->in); ast_cond_destroy(&shutdown_data->out); }
static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan) { struct ast_datastore *datastore = NULL; struct mixmonitor_ds *mixmonitor_ds; if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) { return -1; } ast_mutex_init(&mixmonitor_ds->lock); ast_cond_init(&mixmonitor_ds->destruction_condition, NULL); if (!(datastore = ast_datastore_alloc(&mixmonitor_ds_info, NULL))) { ast_mutex_destroy(&mixmonitor_ds->lock); ast_cond_destroy(&mixmonitor_ds->destruction_condition); ast_free(mixmonitor_ds); return -1; } /* No need to lock mixmonitor_ds since this is still operating in the channel's thread */ mixmonitor_ds->chan = chan; mixmonitor_ds->audiohook = &mixmonitor->audiohook; datastore->data = mixmonitor_ds; ast_channel_lock(chan); ast_channel_datastore_add(chan, datastore); ast_channel_unlock(chan); mixmonitor->mixmonitor_ds = mixmonitor_ds; return 0; }
/*! \brief Called when a channel should be hung up */ static int bridge_hangup(struct ast_channel *ast) { struct bridge_pvt *p = ast->tech_pvt; ast_mutex_lock(&p->lock); /* Figure out which channel this is... and set it to NULL as it has gone, but also queue up a hangup frame. */ if (p->input == ast) { if (p->output) { bridge_queue_hangup(p, ast); } p->input = NULL; } else if (p->output == ast) { if (p->input) { bridge_queue_hangup(p, ast); } p->output = NULL; } /* Deal with the Asterisk portion of it */ ast->tech_pvt = NULL; /* If both sides have been terminated free the structure and be done with things */ if (!p->input && !p->output) { ast_mutex_unlock(&p->lock); ast_mutex_destroy(&p->lock); ast_free(p); } else { ast_mutex_unlock(&p->lock); } return 0; }
static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan, char **datastore_id) { struct ast_datastore *datastore = NULL; struct mixmonitor_ds *mixmonitor_ds; if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) { return -1; } if (ast_asprintf(datastore_id, "%p", mixmonitor_ds) == -1) { ast_log(LOG_ERROR, "Failed to allocate memory for MixMonitor ID.\n"); } ast_mutex_init(&mixmonitor_ds->lock); ast_cond_init(&mixmonitor_ds->destruction_condition, NULL); if (!(datastore = ast_datastore_alloc(&mixmonitor_ds_info, *datastore_id))) { ast_mutex_destroy(&mixmonitor_ds->lock); ast_cond_destroy(&mixmonitor_ds->destruction_condition); ast_free(mixmonitor_ds); return -1; } mixmonitor_ds->samp_rate = 8000; mixmonitor_ds->audiohook = &mixmonitor->audiohook; datastore->data = mixmonitor_ds; ast_channel_lock(chan); ast_channel_datastore_add(chan, datastore); ast_channel_unlock(chan); mixmonitor->mixmonitor_ds = mixmonitor_ds; return 0; }
static void recurring_data_destructor(void *obj) { struct recurring_data *rdata = obj; ast_mutex_destroy(&rdata->lock); ast_cond_destroy(&rdata->cond); }
int ooh323c_start_call_thread(ooCallData *call) { char c = 'c'; struct callthread *cur = callThreads; ast_mutex_lock(&callThreadsLock); while (cur != NULL && (cur->inUse || ast_mutex_trylock(&cur->lock))) { cur = cur->next; } ast_mutex_unlock(&callThreadsLock); if (cur != NULL) { if (cur->inUse || write(cur->thePipe[1], &c, 1) < 0) { ast_mutex_unlock(&cur->lock); cur = NULL; } } /* make new thread */ if (cur == NULL) { if (!(cur = ast_calloc(1, sizeof(struct callthread)))) { ast_log(LOG_ERROR, "Unable to allocate thread structure for call %s\n", call->callToken); return -1; } ast_module_ref(myself); if ((socketpair(PF_LOCAL, SOCK_STREAM, 0, cur->thePipe)) == -1) { ast_log(LOG_ERROR, "Can't create thread pipe for call %s\n", call->callToken); ast_free(cur); return -1; } cur->inUse = TRUE; cur->call = call; ast_mutex_init(&cur->lock); if (gH323Debug) ast_debug(1,"new call thread created for call %s\n", call->callToken); if(ast_pthread_create_detached_background(&call->callThread, NULL, ooh323c_call_thread, cur) < 0) { ast_log(LOG_ERROR, "Unable to start ooh323c call thread for call %s\n", call->callToken); ast_mutex_destroy(&cur->lock); close(cur->thePipe[0]); close(cur->thePipe[1]); ast_free(cur); return -1; } } else { if (gH323Debug) ast_debug(1,"using existing call thread for call %s\n", call->callToken); cur->inUse = TRUE; cur->call = call; ast_mutex_unlock(&cur->lock); } return 0; }
void sched_context_destroy(struct sched_context *con) { struct sched *s, *sl; ast_mutex_lock(&con->lock); #ifdef SCHED_MAX_CACHE /* Eliminate the cache */ s = con->schedc; while(s) { sl = s; s = s->next; free(sl); } #endif /* And the queue */ s = con->schedq; while(s) { sl = s; s = s->next; free(sl); } /* And the context */ ast_mutex_unlock(&con->lock); ast_mutex_destroy(&con->lock); free(con); }
static void task_data_dtor(void *obj) { struct task_data *task_data = obj; ast_mutex_destroy(&task_data->lock); ast_cond_destroy(&task_data->cond); }
/*! * \internal \brief Dispatch a message to a subscriber * \param sub The subscriber to dispatch to * \param message The message to send * \param synchronous If non-zero, synchronize on the subscriber receiving * the message */ static void dispatch_message(struct stasis_subscription *sub, struct stasis_message *message, int synchronous) { if (!sub->mailbox) { /* Dispatch directly */ subscription_invoke(sub, message); return; } /* Bump the message for the taskprocessor push. This will get de-ref'd * by the task processor callback. */ ao2_bump(message); if (!synchronous) { if (ast_taskprocessor_push_local(sub->mailbox, dispatch_exec_async, message)) { /* Push failed; ugh. */ ast_log(LOG_ERROR, "Dropping async dispatch\n"); ao2_cleanup(message); } } else { struct sync_task_data std; ast_mutex_init(&std.lock); ast_cond_init(&std.cond, NULL); std.complete = 0; std.task_data = message; if (ast_taskprocessor_push_local(sub->mailbox, dispatch_exec_sync, &std)) { /* Push failed; ugh. */ ast_log(LOG_ERROR, "Dropping sync dispatch\n"); ao2_cleanup(message); ast_mutex_destroy(&std.lock); ast_cond_destroy(&std.cond); return; } ast_mutex_lock(&std.lock); while (!std.complete) { ast_cond_wait(&std.cond, &std.lock); } ast_mutex_unlock(&std.lock); ast_mutex_destroy(&std.lock); ast_cond_destroy(&std.cond); } }
void csel_destroy (struct csel *cs) { ast_mutex_destroy(&cs->lock); cs->m->destroy(cs); free(cs); ast_module_unref(ast_module_info->self); }
/*! * \brief Worker thread destructor * * Called automatically when refcount reaches 0. Shuts * down the worker thread and destroys its component * parts */ static void worker_thread_destroy(void *obj) { struct worker_thread *worker = obj; ast_debug(3, "Destroying worker thread %d\n", worker->id); worker_shutdown(worker); ast_mutex_destroy(&worker->lock); ast_cond_destroy(&worker->cond); }
static void caching_guarantee_dtor(void *obj) { struct caching_guarantee *guarantee = obj; ast_assert(guarantee->done == 1); ast_mutex_destroy(&guarantee->lock); ast_cond_destroy(&guarantee->cond); }
int ooCloseCmdConnection() { close(gH323ep.cmdSock); gH323ep.cmdSock = 0; close(gCmdChan); gCmdChan = 0; ast_mutex_destroy(&gCmdChanLock); return OO_OK; }
static void mixmonitor_free(struct mixmonitor *mixmonitor) { if (mixmonitor) { if (mixmonitor->mixmonitor_ds) { ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock); ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition); ast_free(mixmonitor->mixmonitor_ds); } ast_free(mixmonitor); } }
static int load_module(void) { ast_mutex_init(&args.lock); args.stun_sock = -1; if (__reload(1)) { ast_mutex_destroy(&args.lock); return AST_MODULE_LOAD_DECLINE; } return AST_MODULE_LOAD_SUCCESS; }
int ooCloseCallCmdConnection(OOH323CallData* call) { ast_mutex_lock(call->CmdChanLock); close(call->cmdSock); call->cmdSock = 0; close(call->CmdChan); call->CmdChan = 0; ast_mutex_unlock(call->CmdChanLock); ast_mutex_destroy(call->CmdChanLock); free(call->CmdChanLock); call->CmdChanLock = NULL; return OO_OK; }
void* ooh323c_call_thread(void* dummy) { struct callthread* mycthread = (struct callthread *)dummy; struct pollfd pfds[1]; char c; int res = 0; do { ooMonitorCallChannels((ooCallData*)mycthread->call); mycthread->call = NULL; mycthread->prev = NULL; mycthread->inUse = FALSE; ast_mutex_lock(&callThreadsLock); mycthread->next = callThreads; callThreads = mycthread; if (mycthread->next) mycthread->next->prev = mycthread; ast_mutex_unlock(&callThreadsLock); pfds[0].fd = mycthread->thePipe[0]; pfds[0].events = POLLIN; ooSocketPoll(pfds, 1, SEC_TO_HOLD_THREAD * 1000); if (ooPDRead(pfds, 1, mycthread->thePipe[0])) res = read(mycthread->thePipe[0], &c, 1); ast_mutex_lock(&callThreadsLock); ast_mutex_lock(&mycthread->lock); if (mycthread->prev) mycthread->prev->next = mycthread->next; else callThreads = mycthread->next; if (mycthread->next) mycthread->next->prev = mycthread->prev; ast_mutex_unlock(&mycthread->lock); ast_mutex_unlock(&callThreadsLock); } while (mycthread->call != NULL && res >= 0); ast_mutex_destroy(&mycthread->lock); close(mycthread->thePipe[0]); close(mycthread->thePipe[1]); ast_free(mycthread); ast_module_unref(myself); ast_update_use_count(); return NULL; }
static void mixmonitor_free(struct mixmonitor *mixmonitor) { if (mixmonitor) { if (mixmonitor->mixmonitor_ds) { ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock); ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition); ast_free(mixmonitor->filename_write); ast_free(mixmonitor->filename_read); ast_free(mixmonitor->mixmonitor_ds); ast_free(mixmonitor->name); ast_free(mixmonitor->post_process); } ast_free(mixmonitor); } }
void misdn_cfg_destroy (void) { misdn_cfg_lock(); _free_port_cfg(); _free_general_cfg(); free(port_cfg); free(general_cfg); free(ptp); free(map); misdn_cfg_unlock(); ast_mutex_destroy(&config_mutex); }
static int unload_module(void) { ast_ari_cli_unregister(); if (is_enabled()) { ast_debug(3, "Disabling ARI\n"); ast_http_uri_unlink(&http_uri); } ast_ari_config_destroy(); ao2_cleanup(root_handler); root_handler = NULL; ast_mutex_destroy(&root_handler_lock); ast_json_unref(oom_json); oom_json = NULL; return 0; }
int ooCreateCallCmdConnection(OOH323CallData* call) { int ret = 0; int thePipe[2]; OOTRACEINFO2("INFO: create cmd connect for call: %lx\n", call); call->CmdChanLock = malloc(sizeof(ast_mutex_t)); ast_mutex_init(call->CmdChanLock); if ((ret = socketpair(PF_LOCAL, SOCK_STREAM, 0, thePipe)) == -1) { ast_mutex_destroy(call->CmdChanLock); free(call->CmdChanLock); call->CmdChanLock = NULL; return OO_FAILED; } ast_mutex_lock(call->CmdChanLock); call->cmdSock = thePipe[0]; call->CmdChan = thePipe[1]; ast_mutex_unlock(call->CmdChanLock); return OO_OK; }
void freeContext (OOCTXT* pctxt) { ASN1BOOL saveBuf; ast_mutex_lock(&pctxt->pLock); saveBuf = (pctxt->flags & ASN1SAVEBUF) != 0; if (pctxt->buffer.dynamic && pctxt->buffer.data) { if (saveBuf) { memHeapMarkSaved (&pctxt->pMsgMemHeap, pctxt->buffer.data, TRUE); } else { memHeapFreePtr (&pctxt->pMsgMemHeap, pctxt->buffer.data); } } errFreeParms (&pctxt->errInfo); memHeapRelease (&pctxt->pTypeMemHeap); memHeapRelease (&pctxt->pMsgMemHeap); ast_mutex_unlock(&pctxt->pLock); ast_mutex_destroy(&pctxt->pLock); }
static void stasis_message_sink_dtor(void *obj) { struct stasis_message_sink *sink = obj; { SCOPED_MUTEX(lock, &sink->lock); while (!sink->is_done) { /* Normally waiting forever is bad, but if we're not * done, we're not done. */ ast_cond_wait(&sink->cond, &sink->lock); } } ast_mutex_destroy(&sink->lock); ast_cond_destroy(&sink->cond); while (sink->num_messages > 0) { ao2_cleanup(sink->messages[--sink->num_messages]); } ast_free(sink->messages); sink->messages = NULL; sink->max_messages = 0; }
static void session_instance_destructor(void *obj) { struct ast_tcptls_session_instance *i = obj; ast_mutex_destroy(&i->lock); }
/* * Helper thread to periodically poll the video sources and enqueue the * generated frames directed to the remote party to the channel's queue. * Using a separate thread also helps because the encoding can be * computationally expensive so we don't want to starve the main thread. */ static void *video_thread(void *arg) { struct video_desc *env = arg; int count = 0; char save_display[128] = ""; int i; /* integer variable used as iterator */ /* if sdl_videodriver is set, override the environment. Also, * if it contains 'console' override DISPLAY around the call to SDL_Init * so we use the console as opposed to the x11 version of aalib */ if (!ast_strlen_zero(env->sdl_videodriver)) { /* override */ const char *s = getenv("DISPLAY"); setenv("SDL_VIDEODRIVER", env->sdl_videodriver, 1); if (s && !strcasecmp(env->sdl_videodriver, "aalib-console")) { ast_copy_string(save_display, s, sizeof(save_display)); unsetenv("DISPLAY"); } } sdl_setup(env); if (!ast_strlen_zero(save_display)) { setenv("DISPLAY", save_display, 1); } ast_mutex_init(&env->dec_lock); /* used to sync decoder and renderer */ if (grabber_open(&env->out)) { ast_log(LOG_WARNING, "cannot open local video source\n"); } if (env->out.device_num) { env->out.devices[env->out.device_primary].status_index |= IS_PRIMARY | IS_SECONDARY; } /* even if no device is connected, we must call video_out_init, * as some of the data structures it initializes are * used in get_video_frames() */ video_out_init(env); /* Writes intial status of the sources. */ if (env->gui) { for (i = 0; i < env->out.device_num; i++) { print_message(env->gui->thumb_bd_array[i].board, src_msgs[env->out.devices[i].status_index]); } } for (;;) { struct timespec t = { 0, 50000000 }; /* XXX 20 times/sec */ struct ast_frame *p, *f; struct ast_channel *chan; int fd; char *caption = NULL, buf[160]; /* determine if video format changed */ if (count++ % 10 == 0) { if (env->out.sendvideo && env->out.devices) { snprintf(buf, sizeof(buf), "%s %s %dx%d @@ %dfps %dkbps", env->out.devices[env->out.device_primary].name, env->codec_name, env->enc_in.w, env->enc_in.h, env->out.fps, env->out.bitrate / 1000); } else { sprintf(buf, "hold"); } caption = buf; } /* manage keypad events */ /* XXX here we should always check for events, * otherwise the drag will not work */ if (env->gui) eventhandler(env, caption); /* sleep for a while */ nanosleep(&t, NULL); if (env->in) { struct video_dec_desc *v = env->in; /* * While there is something to display, call the decoder and free * the buffer, possibly enabling the receiver to store new data. */ while (v->dec_in_dpy) { struct fbuf_t *tmp = v->dec_in_dpy; /* store current pointer */ /* decode the frame, but show it only if not frozen */ if (v->d_callbacks->dec_run(v, tmp) && !env->frame_freeze) show_frame(env, WIN_REMOTE); tmp->used = 0; /* mark buffer as free */ tmp->ebit = 0; ast_mutex_lock(&env->dec_lock); if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN]) /* advance to next, circular */ v->dec_in_dpy = &v->dec_in[0]; if (v->dec_in_cur == NULL) /* receiver was idle, enable it... */ v->dec_in_cur = tmp; /* using the slot just freed */ else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */ v->dec_in_dpy = NULL; /* nothing more to display */ ast_mutex_unlock(&env->dec_lock); } } if (env->shutdown) break; f = get_video_frames(env, &p); /* read and display */ if (!f) continue; chan = env->owner; if (chan == NULL) { /* drop the chain of frames, nobody uses them */ while (f) { struct ast_frame *g = AST_LIST_NEXT(f, frame_list); ast_frfree(f); f = g; } continue; } fd = chan->alertpipe[1]; ast_channel_lock(chan); /* AST_LIST_INSERT_TAIL is only good for one frame, cannot use here */ if (chan->readq.first == NULL) { chan->readq.first = f; } else { chan->readq.last->frame_list.next = f; } chan->readq.last = p; /* * more or less same as ast_queue_frame, but extra * write on the alertpipe to signal frames. */ if (fd > -1) { int blah = 1, l = sizeof(blah); for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) { if (write(fd, &blah, l) != l) ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n", chan->name, f->frametype, f->subclass, strerror(errno)); } } ast_channel_unlock(chan); } /* thread terminating, here could call the uninit */ /* uninitialize the local and remote video environments */ env->in = dec_uninit(env->in); video_out_uninit(env); if (env->gui) env->gui = cleanup_sdl(env->gui, env->out.device_num); ast_mutex_destroy(&env->dec_lock); env->shutdown = 0; return NULL; }
int ast_sem_destroy(struct ast_sem *sem) { ast_mutex_destroy(&sem->mutex); ast_cond_destroy(&sem->cond); return 0; }
/*! \brief Free a \ref json_mem block. */ static void json_mem_free(struct json_mem *mem) { mem->magic = 0; ast_mutex_destroy(&mem->mutex); ast_free(mem); }
int ooCleanCall(OOH323CallData *call) { OOCTXT *pctxt; OOTRACEWARN4 ("Cleaning Call (%s, %s)- reason:%s\n", call->callType, call->callToken, ooGetReasonCodeText (call->callEndReason)); /* First clean all the logical channels, if not already cleaned. */ if(call->logicalChans) ooClearAllLogicalChannels(call); /* Close H.245 connection, if not already closed */ if(call->h245SessionState != OO_H245SESSION_CLOSED) ooCloseH245Connection(call); else{ if(call->pH245Channel && call->pH245Channel->outQueue.count > 0) { dListFreeAll(call->pctxt, &(call->pH245Channel->outQueue)); memFreePtr(call->pctxt, call->pH245Channel); } } /* Close H.245 listener, if not already closed */ if(call->h245listener) { ooCloseH245Listener(call); } /* Close H225 connection, if not already closed. */ if (0 != call->pH225Channel && 0 != call->pH225Channel->sock) { ooCloseH225Connection(call); } /* Clean timers */ if(call->timerList.count > 0) { dListFreeAll(call->pctxt, &(call->timerList)); } if(gH323ep.gkClient && !OO_TESTFLAG(call->flags, OO_M_DISABLEGK)) { ooGkClientCleanCall(gH323ep.gkClient, call); } ooRemoveCallFromList (call); OOTRACEINFO3("Removed call (%s, %s) from list\n", call->callType, call->callToken); if(call->pCallFwdData && call->pCallFwdData->fwdedByRemote) { if(gH323ep.h323Callbacks.onCallForwarded) gH323ep.h323Callbacks.onCallForwarded(call); if(ooH323HandleCallFwdRequest(call)!= OO_OK) { OOTRACEERR3("Error:Failed to forward call (%s, %s)\n", call->callType, call->callToken); } } else { if(gH323ep.h323Callbacks.onCallCleared) gH323ep.h323Callbacks.onCallCleared(call); } if (call->rtpMask) { ast_mutex_lock(&call->rtpMask->lock); call->rtpMask->inuse--; ast_mutex_unlock(&call->rtpMask->lock); if ((call->rtpMask->inuse) == 0) { regfree(&call->rtpMask->regex); ast_mutex_destroy(&call->rtpMask->lock); ast_free(call->rtpMask); } } if ((pctxt = call->msgctxt) != NULL) { freeContext(pctxt); ast_free(pctxt); call->msgctxt = NULL; } /* May !!!! Fix it !! */ /* free(pctxt); */ return OO_OK; }
static void *mixmonitor_thread(void *obj) { struct mixmonitor *mixmonitor = obj; struct ast_filestream *fs = NULL; unsigned int oflags; char *ext; int errflag = 0; if (option_verbose > 1) ast_verbose(VERBOSE_PREFIX_2 "Begin MixMonitor Recording %s\n", mixmonitor->name); ast_audiohook_lock(&mixmonitor->audiohook); while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) { struct ast_frame *fr = NULL; ast_audiohook_trigger_wait(&mixmonitor->audiohook); if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) break; if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR))) continue; ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->mixmonitor_ds->chan && ast_bridged_channel(mixmonitor->mixmonitor_ds->chan))) { ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); /* Initialize the file if not already done so */ if (!fs && !errflag) { oflags = O_CREAT | O_WRONLY; oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC; if ((ext = strrchr(mixmonitor->filename, '.'))) *(ext++) = '\0'; else ext = "raw"; if (!(fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0644))) { ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext); errflag = 1; } } /* Write out the frame */ if (fs) ast_writestream(fs, fr); } else { ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); } /* All done! free it. */ ast_frame_free(fr, 0); } ast_audiohook_detach(&mixmonitor->audiohook); ast_audiohook_unlock(&mixmonitor->audiohook); ast_audiohook_destroy(&mixmonitor->audiohook); if (option_verbose > 1) ast_verbose(VERBOSE_PREFIX_2 "End MixMonitor Recording %s\n", mixmonitor->name); if (fs) ast_closestream(fs); if (mixmonitor->post_process) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_2 "Executing [%s]\n", mixmonitor->post_process); ast_safe_system(mixmonitor->post_process); } ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); if (!mixmonitor->mixmonitor_ds->destruction_ok) { ast_cond_wait(&mixmonitor->mixmonitor_ds->destruction_condition, &mixmonitor->mixmonitor_ds->lock); } ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock); ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition); ast_free(mixmonitor->mixmonitor_ds); free(mixmonitor); return NULL; }
/*! * \brief Cleanup global mock resolver data * * This must be called at the end of tests that use the mock resolver */ static void resolver_data_cleanup(void) { ast_mutex_destroy(&test_resolver_data.lock); ast_cond_destroy(&test_resolver_data.cancel_cond); }