Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
autoservice.c File Reference

Automatic channel service routines. More...

#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include "asterisk/_private.h"
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/translate.h"
#include "asterisk/manager.h"
#include "asterisk/chanvars.h"
#include "asterisk/linkedlists.h"
#include "asterisk/indications.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
Include dependency graph for autoservice.c:

Go to the source code of this file.

Data Structures

struct  asent
 
struct  aslist
 

Macros

#define MAX_AUTOMONS   1500
 

Functions

void ast_autoservice_chan_hangup_peer (struct ast_channel *chan, struct ast_channel *peer)
 Put chan into autoservice while hanging up peer. More...
 
int ast_autoservice_ignore (struct ast_channel *chan, enum ast_frame_type ftype)
 Ignore certain frame types. More...
 
void ast_autoservice_init (void)
 
int ast_autoservice_start (struct ast_channel *chan)
 Automatically service a channel for us... More...
 
int ast_autoservice_stop (struct ast_channel *chan)
 Stop servicing a channel for us... More...
 
static void * autoservice_run (void *ign)
 
static void autoservice_shutdown (void)
 

Variables

static int as_chan_list_state
 
static ast_cond_t as_cond
 
static volatile int asexit = 0
 
static struct aslist aslist = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static pthread_t asthread = AST_PTHREADT_NULL
 

Detailed Description

Automatic channel service routines.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Russell Bryant russe.nosp@m.ll@d.nosp@m.igium.nosp@m..com

Definition in file autoservice.c.

Macro Definition Documentation

◆ MAX_AUTOMONS

#define MAX_AUTOMONS   1500

Definition at line 52 of file autoservice.c.

Referenced by autoservice_run().

Function Documentation

◆ ast_autoservice_chan_hangup_peer()

void ast_autoservice_chan_hangup_peer ( struct ast_channel chan,
struct ast_channel peer 
)

Put chan into autoservice while hanging up peer.

Since
11.0
Parameters
chanChan to put into autoservice.
peerChan to run hangup handlers and hangup.
Returns
Nothing

Definition at line 342 of file autoservice.c.

References ast_autoservice_start(), ast_autoservice_stop(), and ast_hangup().

Referenced by app_exec(), bridge_failed_peer_goto(), dial_exec_full(), and try_calling().

343 {
344  if (chan && !ast_autoservice_start(chan)) {
345  ast_hangup(peer);
346  ast_autoservice_stop(chan);
347  } else {
348  ast_hangup(peer);
349  }
350 }
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548

◆ ast_autoservice_ignore()

int ast_autoservice_ignore ( struct ast_channel chan,
enum ast_frame_type  ftype 
)

Ignore certain frame types.

Note
Normally, we cache DTMF, IMAGE, HTML, TEXT, and CONTROL frames while a channel is in autoservice and queue them up when taken out of autoservice. When this is not desireable, this API may be used to cause the channel to ignore those frametypes after the channel is put into autoservice, but before autoservice is stopped.
Return values
0success
-1channel is not in autoservice

Definition at line 352 of file autoservice.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, asent::chan, asent::ignore_frame_types, and asent::list.

353 {
354  struct asent *as;
355  int res = -1;
356 
358  AST_LIST_TRAVERSE(&aslist, as, list) {
359  if (as->chan == chan) {
360  res = 0;
361  as->ignore_frame_types |= (1 << ftype);
362  break;
363  }
364  }
366  return res;
367 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct ast_channel * chan
Definition: autoservice.c:55
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
unsigned int ignore_frame_types
Definition: autoservice.c:62
struct asent::@346 list

◆ ast_autoservice_init()

void ast_autoservice_init ( void  )

Provided by autoservice.c

Definition at line 380 of file autoservice.c.

References as_cond, ast_cond_init, ast_register_cleanup(), autoservice_shutdown(), and NULL.

Referenced by asterisk_daemon().

381 {
384 }
#define ast_cond_init(cond, attr)
Definition: lock.h:199
static void autoservice_shutdown(void)
Definition: autoservice.c:369
#define NULL
Definition: resample.c:96
static ast_cond_t as_cond
Definition: autoservice.c:71
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19

◆ ast_autoservice_start()

int ast_autoservice_start ( struct ast_channel chan)

Automatically service a channel for us...

Return values
0success
-1failure, or the channel is already being autoserviced

Definition at line 200 of file autoservice.c.

References as_cond, ast_calloc, ast_channel_flags(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_cond_signal, ast_debug, AST_FLAG_END_DTMF_ONLY, ast_free, AST_LIST_EMPTY, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_pthread_create_background, AST_PTHREADT_NULL, ast_set_flag, ast_test_flag, ast_thread_is_user_interface(), asthread, autoservice_run(), asent::chan, asent::list, LOG_WARNING, NULL, asent::orig_end_dtmf_flag, and asent::use_count.

Referenced by _macro_exec(), acf_curl_helper(), acf_jabberreceive_read(), acf_odbc_read(), acf_odbc_write(), action_toggle_mute_participants(), app_exec(), ast_app_exec_macro(), ast_app_exec_sub(), ast_audiosocket_connect(), ast_autoservice_chan_hangup_peer(), ast_dtmf_stream(), ast_get_enum(), ast_get_srv(), ast_get_txt(), ast_mf_stream(), begin_dial_prerun(), conf_play(), confbridge_exec(), dial_exec_full(), exec(), findmeexec(), function_realtime_read(), function_realtime_readdestroy(), function_realtime_store(), function_realtime_write(), join_conference_bridge(), lock_read(), lua_autoservice_start(), lua_get_variable_value(), lua_pbx_exec(), lua_set_variable(), lua_set_variable_value(), originate_exec(), osplookup_exec(), pbx_find_extension(), playback_common(), post_join_play_begin(), push_announcer(), realtimefield_read(), ring_one(), shell_helper(), sla_station_exec(), smdi_msg_retrieve_read(), srv_datastore_setup(), system_exec_helper(), try_calling(), trylock_read(), and valid_priv_reply().

201 {
202  int res = 0;
203  struct asent *as;
204 
206  /* User interface threads do not handle channel media. */
207  ast_debug(1, "Thread is a user interface, not putting channel %s into autoservice\n",
208  ast_channel_name(chan));
209  return 0;
210  }
211 
213  AST_LIST_TRAVERSE(&aslist, as, list) {
214  if (as->chan == chan) {
215  as->use_count++;
216  break;
217  }
218  }
220 
221  if (as) {
222  /* Entry exists, autoservice is already handling this channel */
223  return 0;
224  }
225 
226  if (!(as = ast_calloc(1, sizeof(*as))))
227  return -1;
228 
229  /* New entry created */
230  as->chan = chan;
231  as->use_count = 1;
232 
233  ast_channel_lock(chan);
235  if (!as->orig_end_dtmf_flag)
237  ast_channel_unlock(chan);
238 
240 
243  }
244 
246 
247  if (asthread == AST_PTHREADT_NULL) { /* need start the thread */
249  ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
250  /* There will only be a single member in the list at this point,
251  the one we just added. */
252  AST_LIST_REMOVE(&aslist, as, list);
253  ast_free(as);
255  res = -1;
256  } else {
257  pthread_kill(asthread, SIGURG);
258  }
259  }
260 
262 
263  return res;
264 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
static void * autoservice_run(void *ign)
Definition: autoservice.c:78
#define NULL
Definition: resample.c:96
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:855
#define ast_cond_signal(cond)
Definition: lock.h:201
static ast_cond_t as_cond
Definition: autoservice.c:71
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
int ast_thread_is_user_interface(void)
Indicates whether the current thread is a user interface.
Definition: main/utils.c:2996
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_channel * chan
Definition: autoservice.c:55
#define AST_PTHREADT_NULL
Definition: lock.h:66
unsigned int orig_end_dtmf_flag
Definition: autoservice.c:60
unsigned int use_count
Definition: autoservice.c:59
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static pthread_t asthread
Definition: autoservice.c:73
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
struct asent::@346 list

◆ ast_autoservice_stop()

int ast_autoservice_stop ( struct ast_channel chan)

Stop servicing a channel for us...

Note
if chan is locked prior to calling ast_autoservice_stop, it is likely that there will be a deadlock between the thread that calls ast_autoservice_stop and the autoservice thread. It is important that chan is not locked prior to this call
Parameters
chan
Return values
0success
-1error, or the channel has been hungup

Definition at line 266 of file autoservice.c.

References as_chan_list_state, ast_channel_flags(), ast_channel_lock, ast_channel_name(), ast_channel_softhangup_internal_flag(), ast_channel_unlock, ast_clear_flag, ast_debug, AST_FLAG_END_DTMF_ONLY, ast_free, ast_frfree, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, AST_PTHREADT_NULL, ast_queue_frame_head(), ast_thread_is_user_interface(), asthread, asent::chan, asent::deferred_frames, ast_frame::frametype, asent::ignore_frame_types, asent::list, NULL, asent::orig_end_dtmf_flag, and asent::use_count.

Referenced by _macro_exec(), acf_curl_helper(), acf_jabberreceive_read(), acf_odbc_read(), acf_odbc_write(), action_toggle_mute_participants(), app_exec(), array(), ast_app_exec_macro(), ast_app_exec_sub(), ast_audiosocket_connect(), ast_autoservice_chan_hangup_peer(), ast_dtmf_stream(), ast_get_enum(), ast_get_srv(), ast_get_txt(), ast_hangup(), ast_mf_stream(), begin_dial_prerun(), conf_play(), confbridge_exec(), dial_exec_full(), exec(), findmeexec(), function_realtime_read(), function_realtime_readdestroy(), function_realtime_store(), function_realtime_write(), hangup_playback(), join_conference_bridge(), lock_read(), lua_autoservice_stop(), lua_get_variable_value(), lua_pbx_exec(), lua_set_variable(), lua_set_variable_value(), originate_exec(), osplookup_exec(), pbx_find_extension(), playback_common(), post_join_play_begin(), realtimefield_read(), ring_one(), shell_helper(), sla_station_exec(), smdi_msg_retrieve_read(), srv_datastore_setup(), system_exec_helper(), try_calling(), trylock_read(), and valid_priv_reply().

267 {
268  int res = -1;
269  struct asent *as, *removed = NULL;
270  struct ast_frame *f;
271  int chan_list_state;
272 
274  /* User interface threads do not handle channel media. */
275  ast_debug(1, "Thread is a user interface, not removing channel %s from autoservice\n",
276  ast_channel_name(chan));
277  return 0;
278  }
279 
281 
282  /* Save the autoservice channel list state. We _must_ verify that the channel
283  * list has been rebuilt before we return. Because, after we return, the channel
284  * could get destroyed and we don't want our poor autoservice thread to step on
285  * it after its gone! */
286  chan_list_state = as_chan_list_state;
287 
288  /* Find the entry, but do not free it because it still can be in the
289  autoservice thread array */
291  if (as->chan == chan) {
292  as->use_count--;
293  if (as->use_count < 1) {
295  removed = as;
296  }
297  break;
298  }
299  }
301 
302  if (removed && asthread != AST_PTHREADT_NULL) {
303  pthread_kill(asthread, SIGURG);
304  }
305 
307 
308  if (!removed) {
309  return 0;
310  }
311 
312  /* Wait while autoservice thread rebuilds its list. */
313  while (chan_list_state == as_chan_list_state) {
314  usleep(1000);
315  }
316 
317  /* Now autoservice thread should have no references to our entry
318  and we can safely destroy it */
319 
321  res = 0;
322  }
323 
324  ast_channel_lock(chan);
325  if (!as->orig_end_dtmf_flag) {
327  }
328 
329  while ((f = AST_LIST_REMOVE_HEAD(&as->deferred_frames, frame_list))) {
330  if (!((1 << f->frametype) & as->ignore_frame_types)) {
331  ast_queue_frame_head(chan, f);
332  }
333  ast_frfree(f);
334  }
335  ast_channel_unlock(chan);
336 
337  ast_free(as);
338 
339  return res;
340 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define NULL
Definition: resample.c:96
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
int ast_thread_is_user_interface(void)
Indicates whether the current thread is a user interface.
Definition: main/utils.c:2996
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static int as_chan_list_state
Definition: autoservice.c:76
struct ast_channel * chan
Definition: autoservice.c:55
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
unsigned int orig_end_dtmf_flag
Definition: autoservice.c:60
unsigned int use_count
Definition: autoservice.c:59
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_free(a)
Definition: astmm.h:182
static pthread_t asthread
Definition: autoservice.c:73
#define ast_clear_flag(p, flag)
Definition: utils.h:77
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
const char * ast_channel_name(const struct ast_channel *chan)
struct asent::@345 deferred_frames
#define ast_frfree(fr)
Data structure associated with a single frame of data.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
enum ast_frame_type frametype
unsigned int ignore_frame_types
Definition: autoservice.c:62
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
int ast_queue_frame_head(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to the head of a channel&#39;s frame queue.
Definition: channel.c:1144

◆ autoservice_run()

static void* autoservice_run ( void *  ign)
static

Definition at line 78 of file autoservice.c.

References as_chan_list_state, as_cond, asexit, ast_callid_threadassoc_change(), ast_channel_callid(), ast_check_hangup(), ast_cond_wait, AST_CONTROL_HANGUP, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, ast_frdup, ast_frfree, ast_frisolate, ast_is_deferrable_frame(), AST_LIST_EMPTY, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, AST_PTHREADT_NULL, ast_read(), ast_waitfor_n(), asthread, ast_channel::callid, asent::chan, asent::deferred_frames, ast_frame::frametype, ast_frame_subclass::integer, asent::list, aslist::lock, LOG_WARNING, MAX_AUTOMONS, NULL, ast_frame::subclass, and asent::video_update.

Referenced by ast_autoservice_start().

79 {
80  ast_callid callid = 0;
81  struct ast_frame hangup_frame = {
83  .subclass.integer = AST_CONTROL_HANGUP,
84  };
85 
86  while (!asexit) {
87  struct ast_channel *mons[MAX_AUTOMONS];
88  struct asent *ents[MAX_AUTOMONS];
89  struct ast_channel *chan;
90  struct asent *as;
91  int i, x = 0, ms = 50;
92  struct ast_frame *f = NULL;
93  struct ast_frame *defer_frame = NULL;
94 
96 
97  /* At this point, we know that no channels that have been removed are going
98  * to get used again. */
100 
101  if (AST_LIST_EMPTY(&aslist)) {
103  }
104 
105  AST_LIST_TRAVERSE(&aslist, as, list) {
106  if (!ast_check_hangup(as->chan)) {
107  if (x < MAX_AUTOMONS) {
108  ents[x] = as;
109  mons[x++] = as->chan;
110  } else {
111  ast_log(LOG_WARNING, "Exceeded maximum number of automatic monitoring events. Fix autoservice.c\n");
112  }
113  }
114  }
115 
117 
118  if (!x) {
119  /* If we don't sleep, this becomes a busy loop, which causes
120  * problems when Asterisk runs at a different priority than other
121  * user processes. As long as we check for new channels at least
122  * once every 10ms, we should be fine. */
123  usleep(10000);
124  continue;
125  }
126 
127  chan = ast_waitfor_n(mons, x, &ms);
128  if (!chan) {
129  continue;
130  }
131 
132  callid = ast_channel_callid(chan);
134 
135  f = ast_read(chan);
136 
137  if (!f) {
138  /* No frame means the channel has been hung up.
139  * A hangup frame needs to be queued here as ast_waitfor() may
140  * never return again for the condition to be detected outside
141  * of autoservice. So, we'll leave a HANGUP queued up so the
142  * thread in charge of this channel will know. */
143 
144  defer_frame = &hangup_frame;
145  } else if (ast_is_deferrable_frame(f)) {
146  defer_frame = f;
147  } else {
148  /* Can't defer. Discard and continue with next. */
149  ast_frfree(f);
150  continue;
151  }
152 
153  for (i = 0; i < x; i++) {
154  struct ast_frame *dup_f;
155 
156  if (mons[i] != chan) {
157  continue;
158  }
159 
160  if (!f) { /* defer_frame == &hangup_frame */
161  if ((dup_f = ast_frdup(defer_frame))) {
162  AST_LIST_INSERT_HEAD(&ents[i]->deferred_frames, dup_f, frame_list);
163  }
164  } else {
165  if (defer_frame->frametype == AST_FRAME_CONTROL &&
166  defer_frame->subclass.integer == AST_CONTROL_VIDUPDATE) {
167 
168  /* If a video update is already queued don't needlessly queue another */
169  if (ents[i]->video_update) {
170  ast_frfree(defer_frame);
171  break;
172  }
173 
174  ents[i]->video_update = 1;
175  }
176  if ((dup_f = ast_frisolate(defer_frame))) {
177  AST_LIST_INSERT_HEAD(&ents[i]->deferred_frames, dup_f, frame_list);
178  }
179  if (dup_f != defer_frame) {
180  ast_frfree(defer_frame);
181  }
182  }
183 
184  break;
185  }
186  /* The ast_waitfor_n() call will only read frames from
187  * the channels' file descriptors. If ast_waitfor_n()
188  * returns non-NULL, then one of the channels in the
189  * mons array must have triggered the return. It's
190  * therefore impossible that we got here while (i >= x).
191  * If we did, we'd need to ast_frfree(f) if (f). */
192  }
193 
196 
197  return NULL;
198 }
static volatile int asexit
Definition: autoservice.c:74
struct ast_channel * ast_waitfor_n(struct ast_channel **chan, int n, int *ms)
Waits for input on a group of channels Wait for input on an array of channels for a given # of millis...
Definition: channel.c:3166
Main Channel structure associated with a channel.
#define ast_frdup(fr)
Copies a frame.
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
unsigned int video_update
Definition: autoservice.c:61
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define MAX_AUTOMONS
Definition: autoservice.c:52
int ast_callid_threadassoc_change(ast_callid callid)
Sets what is stored in the thread storage to the given callid if it does not match what is already th...
Definition: logger.c:1971
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
unsigned int ast_callid
Definition: logger.h:87
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define NULL
Definition: resample.c:96
struct ast_frame_subclass subclass
ast_mutex_t lock
Definition: autoservice.c:70
static ast_cond_t as_cond
Definition: autoservice.c:71
#define ast_log
Definition: astobj2.c:42
static int as_chan_list_state
Definition: autoservice.c:76
struct ast_channel * chan
Definition: autoservice.c:55
#define AST_PTHREADT_NULL
Definition: lock.h:66
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
static pthread_t asthread
Definition: autoservice.c:73
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_frfree(fr)
int ast_is_deferrable_frame(const struct ast_frame *frame)
Should we keep this frame for later?
Definition: channel.c:1467
Data structure associated with a single frame of data.
enum ast_frame_type frametype
ast_callid ast_channel_callid(const struct ast_channel *chan)

◆ autoservice_shutdown()

static void autoservice_shutdown ( void  )
static

Definition at line 369 of file autoservice.c.

References as_cond, asexit, ast_cond_signal, AST_PTHREADT_NULL, asthread, and NULL.

Referenced by ast_autoservice_init().

370 {
371  pthread_t th = asthread;
372  asexit = 1;
373  if (th != AST_PTHREADT_NULL) {
375  pthread_kill(th, SIGURG);
376  pthread_join(th, NULL);
377  }
378 }
static volatile int asexit
Definition: autoservice.c:74
#define NULL
Definition: resample.c:96
#define ast_cond_signal(cond)
Definition: lock.h:201
static ast_cond_t as_cond
Definition: autoservice.c:71
#define AST_PTHREADT_NULL
Definition: lock.h:66
static pthread_t asthread
Definition: autoservice.c:73

Variable Documentation

◆ as_chan_list_state

int as_chan_list_state
static

Definition at line 76 of file autoservice.c.

Referenced by ast_autoservice_stop(), and autoservice_run().

◆ as_cond

ast_cond_t as_cond
static

◆ asexit

volatile int asexit = 0
static

Definition at line 74 of file autoservice.c.

Referenced by autoservice_run(), and autoservice_shutdown().

◆ aslist

struct aslist aslist = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ asthread

pthread_t asthread = AST_PTHREADT_NULL
static