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

Functions implementing astobj2 objects. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/astobj2.h"
#include "astobj2_private.h"
#include "astobj2_container_private.h"
#include "asterisk/cli.h"
#include "asterisk/paths.h"

Go to the source code of this file.

Data Structures

struct  __priv_data
 
struct  ao2_lock_priv
 
struct  ao2_lockobj_priv
 
struct  ao2_rwlock_priv
 
struct  ao2_weakproxy_notification
 
struct  astobj2
 
struct  astobj2_lock
 
struct  astobj2_lockobj
 
struct  astobj2_rwlock
 

Macros

#define __INTERNAL_OBJ_CHECK(user_data, file, line, func)
 convert from a pointer _p to a user-defined object More...
 
#define AO2_MAGIC   0xa70b123
 
#define AO2_WEAK   0xa70b122
 
#define ast_log   ast_log_safe
 
#define DEBUG_THREADS_LOOSE_ABI
 
#define EXCESSIVE_REF_COUNT   100000
 
#define EXTERNAL_OBJ(_p)   ((_p) == NULL ? NULL : (_p)->user_data)
 convert from a pointer _p to an astobj2 object More...
 
#define INTERNAL_OBJ(user_data)   (struct astobj2 *) ((char *) user_data - sizeof(struct astobj2))
 
#define INTERNAL_OBJ_CHECK(user_data)   __INTERNAL_OBJ_CHECK(user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
#define INTERNAL_OBJ_LOCKOBJ(user_data)   ((struct astobj2_lockobj *) (((char *) (user_data)) - sizeof(struct astobj2_lockobj)))
 
#define INTERNAL_OBJ_MUTEX(user_data)   ((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock)))
 
#define INTERNAL_OBJ_RWLOCK(user_data)   ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
 
#define IS_AO2_MAGIC_BAD(p)   (AO2_MAGIC != (p->priv_data.magic | 1))
 

Functions

enum ao2_lock_req __adjust_lock (void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
 
void * __ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag, const char *file, int line, const char *func)
 
void * __ao2_alloc_with_lockobj (size_t data_size, ao2_destructor_fn destructor_fn, void *lockobj, const char *tag, const char *file, int line, const char *func)
 
void __ao2_cleanup (void *obj)
 
void __ao2_cleanup_debug (void *obj, const char *tag, const char *file, int line, const char *function)
 
void * __ao2_get_weakproxy (void *obj, const char *tag, const char *file, int line, const char *func)
 
int __ao2_lock (void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
 Lock an object. More...
 
int __ao2_ref (void *user_data, int delta, const char *tag, const char *file, int line, const char *func)
 
int __ao2_trylock (void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
 Try locking– (don't block if fail) More...
 
int __ao2_unlock (void *user_data, const char *file, const char *func, int line, const char *var)
 Unlock an object. More...
 
void * __ao2_weakproxy_alloc (size_t data_size, ao2_destructor_fn destructor_fn, const char *tag, const char *file, int line, const char *func)
 
void * __ao2_weakproxy_get_object (void *weakproxy, int flags, const char *tag, const char *file, int line, const char *func)
 
int __ao2_weakproxy_ref_object (void *weakproxy, int delta, int flags, const char *tag, const char *file, int line, const char *func)
 
int __ao2_weakproxy_set_object (void *weakproxy, void *obj, int flags, const char *tag, const char *file, int line, const char *func)
 
void * ao2_object_get_lockaddr (void *user_data)
 Return the mutex lock address of an object. More...
 
unsigned int ao2_options_get (void *obj)
 Retrieve the ao2 options used to create the object. More...
 
int ao2_weakproxy_subscribe (void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags)
 Request notification when weakproxy points to NULL. More...
 
int ao2_weakproxy_unsubscribe (void *weakproxy, ao2_weakproxy_notification_cb destroyed_cb, void *data, int flags)
 Remove notification of real object destruction. More...
 
static void astobj2_cleanup (void)
 
int astobj2_init (void)
 
static void * internal_ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, void *lockobj, const char *tag, const char *file, int line, const char *func)
 
int internal_is_ao2_object (void *user_data)
 
void log_bad_ao2 (void *user_data, const char *file, int line, const char *func)
 

Variables

static FILE * ref_log
 

Detailed Description

Functions implementing astobj2 objects.

Author
Richard Mudgett rmudg.nosp@m.ett@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file astobj2.c.

Macro Definition Documentation

#define __INTERNAL_OBJ_CHECK (   user_data,
  file,
  line,
  func 
)

convert from a pointer _p to a user-defined object

Returns
the pointer to the astobj2 structure

Definition at line 171 of file astobj2.c.

Referenced by __ao2_lock(), __ao2_trylock(), and __ao2_unlock().

#define EXTERNAL_OBJ (   _p)    ((_p) == NULL ? NULL : (_p)->user_data)

convert from a pointer _p to an astobj2 object

Returns
the pointer to the user-defined portion.

Definition at line 191 of file astobj2.c.

Function Documentation

void __ao2_cleanup ( void *  obj)

gcc attribute(cleanup()) functions

Note
they must be able to handle NULL parameters because most of the allocation/find functions can fail and we don't want to try to tear down a NULL

Definition at line 677 of file astobj2.c.

References ao2_ref.

Referenced by agent_request_exec(), ast_ari_bridges_set_video_source(), bridge_agent_hold_push(), dial_bridge_after_cb(), and parking_set_duration().

678 {
679  if (obj) {
680  ao2_ref(obj, -1);
681  }
682 }
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
int __ao2_lock ( void *  a,
enum ao2_lock_req  lock_how,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Lock an object.

Parameters
aA pointer to the object we want to lock.
lock_how,file,func,line,var
Returns
0 on success, other values on error.

Definition at line 222 of file astobj2.c.

References __INTERNAL_OBJ_CHECK, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ast_atomic_fetchadd_int(), __priv_data::lockused, ao2_rwlock_priv::num_lockers, and __priv_data::options.

223 {
224  struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
225  struct astobj2_lock *obj_mutex;
226  struct astobj2_rwlock *obj_rwlock;
227  struct astobj2_lockobj *obj_lockobj;
228  int res = 0;
229 
230  if (obj == NULL) {
231  return -1;
232  }
233 
234  if (ref_log) {
235  obj->priv_data.lockused = 1;
236  }
237 
238  switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
240  obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
241  res = __ast_pthread_mutex_lock(file, line, func, var, &obj_mutex->mutex.lock);
242 #ifdef AO2_DEBUG
243  if (!res) {
244  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
245  }
246 #endif
247  break;
249  obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
250  switch (lock_how) {
251  case AO2_LOCK_REQ_MUTEX:
252  case AO2_LOCK_REQ_WRLOCK:
253  res = __ast_rwlock_wrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
254  if (!res) {
255  ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
256 #ifdef AO2_DEBUG
257  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
258 #endif
259  }
260  break;
261  case AO2_LOCK_REQ_RDLOCK:
262  res = __ast_rwlock_rdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
263  if (!res) {
264  ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
265 #ifdef AO2_DEBUG
266  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
267 #endif
268  }
269  break;
270  }
271  break;
273  /* The ao2 object has no lock. */
274  break;
275  case AO2_ALLOC_OPT_LOCK_OBJ:
276  obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
277  res = __ao2_lock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var);
278  break;
279  default:
280  ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
281  user_data);
282  return -1;
283  }
284 
285  return res;
286 }
uint32_t options
The ao2 object option flags.
Definition: astobj2.c:70
int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
Lock an object.
Definition: astobj2.c:222
#define __INTERNAL_OBJ_CHECK(user_data, file, line, func)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:171
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
uint32_t lockused
Set to 1 when the lock is used if refdebug is enabled.
Definition: astobj2.c:77
int __ao2_trylock ( void *  a,
enum ao2_lock_req  lock_how,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Try locking– (don't block if fail)

Parameters
aA pointer to the object we want to lock.
lock_how,file,func,line,var
Returns
0 on success, other values on error.

Definition at line 342 of file astobj2.c.

References __INTERNAL_OBJ_CHECK, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ast_atomic_fetchadd_int(), __priv_data::lockused, ao2_rwlock_priv::num_lockers, and __priv_data::options.

343 {
344  struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
345  struct astobj2_lock *obj_mutex;
346  struct astobj2_rwlock *obj_rwlock;
347  struct astobj2_lockobj *obj_lockobj;
348  int res = 0;
349 
350  if (obj == NULL) {
351  return -1;
352  }
353 
354  if (ref_log) {
355  obj->priv_data.lockused = 1;
356  }
357 
358  switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
360  obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
361  res = __ast_pthread_mutex_trylock(file, line, func, var, &obj_mutex->mutex.lock);
362 #ifdef AO2_DEBUG
363  if (!res) {
364  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
365  }
366 #endif
367  break;
369  obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
370  switch (lock_how) {
371  case AO2_LOCK_REQ_MUTEX:
372  case AO2_LOCK_REQ_WRLOCK:
373  res = __ast_rwlock_trywrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
374  if (!res) {
375  ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
376 #ifdef AO2_DEBUG
377  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
378 #endif
379  }
380  break;
381  case AO2_LOCK_REQ_RDLOCK:
382  res = __ast_rwlock_tryrdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
383  if (!res) {
384  ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
385 #ifdef AO2_DEBUG
386  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
387 #endif
388  }
389  break;
390  }
391  break;
393  /* The ao2 object has no lock. */
394  return 0;
395  case AO2_ALLOC_OPT_LOCK_OBJ:
396  obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
397  res = __ao2_trylock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var);
398  break;
399  default:
400  ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
401  user_data);
402  return -1;
403  }
404 
405  return res;
406 }
int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
Try locking– (don't block if fail)
Definition: astobj2.c:342
uint32_t options
The ao2 object option flags.
Definition: astobj2.c:70
#define __INTERNAL_OBJ_CHECK(user_data, file, line, func)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:171
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
uint32_t lockused
Set to 1 when the lock is used if refdebug is enabled.
Definition: astobj2.c:77
int __ao2_unlock ( void *  a,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Unlock an object.

Parameters
aA pointer to the object we want unlock.
file,func,line,var
Returns
0 on success, other values on error.

Definition at line 288 of file astobj2.c.

References __INTERNAL_OBJ_CHECK, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_RWLOCK, ast_atomic_fetchadd_int(), ao2_rwlock_priv::num_lockers, and __priv_data::options.

289 {
290  struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
291  struct astobj2_lock *obj_mutex;
292  struct astobj2_rwlock *obj_rwlock;
293  struct astobj2_lockobj *obj_lockobj;
294  int res = 0;
295  int current_value;
296 
297  if (obj == NULL) {
298  return -1;
299  }
300 
301  switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
303  obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
304  res = __ast_pthread_mutex_unlock(file, line, func, var, &obj_mutex->mutex.lock);
305 #ifdef AO2_DEBUG
306  if (!res) {
307  ast_atomic_fetchadd_int(&ao2.total_locked, -1);
308  }
309 #endif
310  break;
312  obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
313 
314  current_value = ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1) - 1;
315  if (current_value < 0) {
316  /* It was a WRLOCK that we are unlocking. Fix the count. */
317  ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -current_value);
318  }
319  res = __ast_rwlock_unlock(file, line, func, &obj_rwlock->rwlock.lock, var);
320 #ifdef AO2_DEBUG
321  if (!res) {
322  ast_atomic_fetchadd_int(&ao2.total_locked, -1);
323  }
324 #endif
325  break;
327  /* The ao2 object has no lock. */
328  break;
329  case AO2_ALLOC_OPT_LOCK_OBJ:
330  obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
331  res = __ao2_unlock(obj_lockobj->lockobj.lock, file, func, line, var);
332  break;
333  default:
334  ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
335  user_data);
336  res = -1;
337  break;
338  }
339  return res;
340 }
uint32_t options
The ao2 object option flags.
Definition: astobj2.c:70
#define __INTERNAL_OBJ_CHECK(user_data, file, line, func)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:171
int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
Unlock an object.
Definition: astobj2.c:288
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
void* ao2_object_get_lockaddr ( void *  obj)

Return the mutex lock address of an object.

Parameters
[in]objA pointer to the object we want.
Returns
the address of the mutex lock, else NULL.

This function comes in handy mainly for debugging locking situations, where the locking trace code reports the lock address, this allows you to correlate against object address, to match objects to reported locks.

Warning
AO2 lock objects do not include tracking fields when DEBUG_THREADS is not enabled.
Since
1.6.1

Definition at line 476 of file astobj2.c.

References AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, and __priv_data::options.

Referenced by ast_rtp_ice_turn_request(), control_wait(), db_sync_thread(), ice_reset_session(), and stasis_subscription_join().

477 {
478  struct astobj2 *obj;
479  struct astobj2_lock *obj_mutex;
480 
481  obj = INTERNAL_OBJ_CHECK(user_data);
482 
483  if (obj == NULL) {
484  return NULL;
485  }
486 
487  switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
489  obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
490  return &obj_mutex->mutex.lock;
491  default:
492  break;
493  }
494 
495  return NULL;
496 }
uint32_t options
The ao2 object option flags.
Definition: astobj2.c:70
unsigned int ao2_options_get ( void *  obj)

Retrieve the ao2 options used to create the object.

Parameters
objpointer to the (user-defined part) of an object.
Returns
options from enum ao2_alloc_opts.

Definition at line 781 of file astobj2.c.

References __priv_data::options.

782 {
783  struct astobj2 *orig_obj;
784 
785  orig_obj = INTERNAL_OBJ_CHECK(obj);
786  if (!orig_obj) {
787  return 0;
788  }
789  return orig_obj->priv_data.options;
790 }
uint32_t options
The ao2 object option flags.
Definition: astobj2.c:70
int ao2_weakproxy_subscribe ( void *  weakproxy,
ao2_weakproxy_notification_cb  cb,
void *  data,
int  flags 
)

Request notification when weakproxy points to NULL.

Since
14.0.0
Parameters
weakproxyThe weak object
cbProcedure to call when no real object is associated
dataPassed to cb
flagsOBJ_NOLOCK to avoid locking weakproxy.
Return values
0Success
-1Failure
Note
Callbacks are run in the reverse order of subscriptions.
This procedure will allow the same cb / data pair to be added to the same weakproxy multiple times.
It is the caller's responsibility to ensure that *data is valid until after cb() is run or ao2_weakproxy_unsubscribe is called.
If the weakproxy currently points to NULL the callback will be run immediately, without being added to the subscriber list.

Definition at line 934 of file astobj2.c.

References ast_calloc, AST_LIST_INSERT_HEAD, and __priv_data::weakptr.

935 {
936  struct astobj2 *weakproxy_internal = INTERNAL_OBJ_CHECK(weakproxy);
937  int ret = -1;
938  int hasobj;
939 
940  if (!weakproxy_internal || weakproxy_internal->priv_data.magic != AO2_WEAK) {
941  return -1;
942  }
943 
944  if (!(flags & OBJ_NOLOCK)) {
945  ao2_lock(weakproxy);
946  }
947 
948  hasobj = weakproxy_internal->priv_data.weakptr != NULL;
949  if (hasobj) {
950  struct ao2_weakproxy *weak = weakproxy;
951  struct ao2_weakproxy_notification *sub = ast_calloc(1, sizeof(*sub));
952 
953  if (sub) {
954  sub->cb = cb;
955  sub->data = data;
956  AST_LIST_INSERT_HEAD(&weak->destroyed_cb, sub, list);
957  ret = 0;
958  }
959  }
960 
961  if (!(flags & OBJ_NOLOCK)) {
962  ao2_unlock(weakproxy);
963  }
964 
965  if (!hasobj) {
966  cb(weakproxy, data);
967  ret = 0;
968  }
969 
970  return ret;
971 }
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
void * weakptr
Definition: astobj2.c:57
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
This struct should be opaque, but it's size is needed.
Definition: astobj2.h:529
int ao2_weakproxy_unsubscribe ( void *  weakproxy,
ao2_weakproxy_notification_cb  cb,
void *  data,
int  flags 
)

Remove notification of real object destruction.

Since
14.0.0
Parameters
weakproxyThe weak object
cbCallback to remove from destroy notification list
dataData pointer to match
flagsOBJ_NOLOCK to avoid locking weakproxy. OBJ_MULTIPLE to remove all copies of the same cb / data pair.
Returns
The number of subscriptions removed.
Return values
0cb / data pair not found, nothing removed.
-1Failure due to invalid parameters.
Note
Unless flags includes OBJ_MULTIPLE, this will only remove a single copy of the cb / data pair. If it was subscribed multiple times it must be unsubscribed as many times. The OBJ_MULTIPLE flag can be used to remove matching subscriptions.
When it's time to run callbacks they are copied to a temporary list so the weakproxy can be unlocked before running. That means it's possible for this function to find nothing before the callback is run in another thread.

Definition at line 973 of file astobj2.c.

References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, and OBJ_MULTIPLE.

974 {
975  struct astobj2 *internal_weakproxy = INTERNAL_OBJ_CHECK(weakproxy);
976  struct ao2_weakproxy *weak;
977  struct ao2_weakproxy_notification *sub;
978  int ret = 0;
979 
980  if (!internal_weakproxy || internal_weakproxy->priv_data.magic != AO2_WEAK || !destroyed_cb) {
981  return -1;
982  }
983 
984  if (!(flags & OBJ_NOLOCK)) {
985  ao2_lock(weakproxy);
986  }
987 
988  weak = weakproxy;
989  AST_LIST_TRAVERSE_SAFE_BEGIN(&weak->destroyed_cb, sub, list) {
990  if (sub->cb == destroyed_cb && sub->data == data) {
992  ast_free(sub);
993  ret++;
994  if (!(flags & OBJ_MULTIPLE)) {
995  break;
996  }
997  }
998  }
1000 
1001  if (!(flags & OBJ_NOLOCK)) {
1002  ao2_unlock(weakproxy);
1003  }
1004 
1005  return ret;
1006 }
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
This struct should be opaque, but it's size is needed.
Definition: astobj2.h:529
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
int astobj2_init ( void  )

Provided by astobj2.c

Definition at line 1169 of file astobj2.c.

References ast_cli_register_multiple, and ast_register_cleanup().

1170 {
1171  char ref_filename[1024];
1172 
1173  if (ast_opt_ref_debug) {
1174  snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR);
1175  ref_log = fopen(ref_filename, "w");
1176  if (!ref_log) {
1177  ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename);
1178  }
1179  }
1180 
1181  ast_register_cleanup(astobj2_cleanup);
1182 
1183  if (container_init() != 0) {
1184  fclose(ref_log);
1185  ref_log = NULL;
1186  return -1;
1187  }
1188 
1189 #if defined(AO2_DEBUG)
1190  ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
1191 #endif /* defined(AO2_DEBUG) */
1192 
1193  return 0;
1194 }
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19