diff --git a/Makefile b/Makefile index c5505ccf690c7f36e7952111e006ad02fb494331..41c824325604ce158718ebe6129300e5368b78ed 100755 --- a/Makefile +++ b/Makefile @@ -26,15 +26,12 @@ PROC=k8 #PROC=athlon OPTIONS+=-m64 endif -else -ifeq (${OSARCH},FreeBSD) -PROC=$(shell uname -m) -else -ifeq (${OSARCH},OpenBSD) -PROC=$(shell uname -m) -endif endif + +ifeq ($(findstring BSD,${OSARCH}),BSD) +PROC=$(shell uname -m) endif + # Pentium Pro Optimize #PROC=i686 @@ -120,10 +117,15 @@ CFLAGS=-pipe -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarati CFLAGS+=$(OPTIMIZE) CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi) CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi) + ifeq (${OSARCH},FreeBSD) -CFLAGS+=-pthread +OSVERSION=$(shell make -V OSVERSION -f /usr/share/mk/bsd.port.subdir.mk) +CFLAGS+=$(if ${OSVERSION}<500016,-D_THREAD_SAFE) +LIBS+=$(if ${OSVERSION}<502102,-lc_r,-pthread) INCLUDE+=-I/usr/local/include -endif +CFLAGS+=$(shell if [ -d /usr/local/include/spandsp ]; then echo "-I/usr/local/include/spandsp"; fi) +endif # FreeBSD + ifeq (${OSARCH},OpenBSD) CFLAGS+=-pthread endif @@ -161,14 +163,6 @@ SUBDIRS=res channels pbx apps codecs formats agi cdr astman stdtime ifeq (${OSARCH},Linux) LIBS=-ldl -lpthread endif -ifeq (${OSARCH},OpenBSD) -LIBS=-pthread -else -ifeq (${OSARCH},FreeBSD) -LIBS=-pthread -else -endif -endif LIBS+=-lncurses -lm ifeq (${OSARCH},Linux) LIBS+=-lresolv #-lnjamd diff --git a/agi/Makefile b/agi/Makefile index a0d5a69ccaa3c22d73c9c4acfec6026bba32aba3..2f87df5f87add7223012c50a895e35a4879135df 100755 --- a/agi/Makefile +++ b/agi/Makefile @@ -22,10 +22,10 @@ install: all for x in $(AGIS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(AGI_DIR) ; done eagi-test: eagi-test.o - $(CC) -o eagi-test eagi-test.o - + $(CC) $(CFLAGS) -o eagi-test eagi-test.o + eagi-sphinx-test: eagi-sphinx-test.o - $(CC) -o eagi-sphinx-test eagi-sphinx-test.o + $(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o clean: rm -f *.so *.o look .depend eagi-test eagi-sphinx-test diff --git a/apps/app_dial.c b/apps/app_dial.c index 67f82fd733b2f5e9dba472c7cf61a8782987a46f..8b096c40ca9eab85cdeca4b82804266b77e694e4 100755 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -122,7 +122,7 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception } } -#define MAX 256 +#define AST_MAX_WATCHERS 256 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect, int *sentringing) { @@ -133,7 +133,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu int orig = *to; struct ast_frame *f; struct ast_channel *peer = NULL; - struct ast_channel *watchers[MAX]; + struct ast_channel *watchers[AST_MAX_WATCHERS]; int pos; int single; struct ast_channel *winner; diff --git a/apps/app_queue.c b/apps/app_queue.c index a406eea435803890f7a615d69aa47ac672efb4d6..e36bbda8e5ff6d1adf37f3b5c5d1616de668edac 100755 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -330,6 +330,7 @@ static void destroy_queue(struct ast_call_queue *q) } ast_mutex_unlock(&qlock); free_members(q, 1); + ast_mutex_destroy(&q->lock); free(q); } @@ -628,7 +629,7 @@ static int valid_exit(struct queue_ent *qe, char digit) return 0; } -#define MAX 256 +#define AST_MAX_WATCHERS 256 static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect, char *digit) { @@ -641,7 +642,7 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser int orig = *to; struct ast_frame *f; struct localuser *peer = NULL; - struct ast_channel *watchers[MAX]; + struct ast_channel *watchers[AST_MAX_WATCHERS]; int pos; struct ast_channel *winner; struct ast_channel *in = qe->chan; diff --git a/apps/app_rpt.c b/apps/app_rpt.c index a4992cb1e39c26a28c1bc3a47a7f9ff1b9431cf8..9edd77f52583cb62e4f5dc08aeb8a26b767f62a4 100755 --- a/apps/app_rpt.c +++ b/apps/app_rpt.c @@ -2113,7 +2113,10 @@ static int rpt_exec(struct ast_channel *chan, void *data) int unload_module(void) { + int i; STANDARD_HANGUP_LOCALUSERS; + for(i = 0; i < nrpts; i++) { + ast_mutex_destroy(&rpt_vars[i].lock); return ast_unregister_application(app); return 0; } diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index 224f78dacf8f4677cefce1099632c09081130dd8..803ea4c2abaeee9fb0485adc570dc1b636204abd 100755 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -330,7 +330,7 @@ static void apply_options(struct ast_vm_user *vmu, char *options) PGconn *dbhandler; char dboption[256]; -ast_mutex_t postgreslock; +AST_MUTEX_DEFINE_STATIC(postgreslock); static int sql_init(void) { @@ -342,8 +342,6 @@ static int sql_init(void) ast_log(LOG_WARNING, "Error Logging into database %s: %s\n",dboption,PQerrorMessage(dbhandler)); return(-1); } - ast_mutex_init(&postgreslock); - /* fprintf(stderr,"postgres login OK\n"); */ return(0); } diff --git a/asterisk.c b/asterisk.c index 105a02fb7a2d0a1735252000b33a1b2bb4042f39..39a20ec40808360309edfdbbd1c9a4188b50c9a1 100755 --- a/asterisk.c +++ b/asterisk.c @@ -49,6 +49,7 @@ #include "asterisk.h" #include <asterisk/config.h> #include <asterisk/config_pvt.h> +#include <sys/resource.h> #if defined(__FreeBSD__) #include <netdb.h> @@ -1561,6 +1562,11 @@ int main(int argc, char *argv[]) term_init(); printf(term_end()); fflush(stdout); + + /* Test recursive mutex locking. */ + if(test_for_thread_safety()) + ast_verbose("Warning! Asterisk is not thread safe.\n"); + if (option_console && !option_verbose) ast_verbose("[ Reading Master Configuration ]"); ast_readconfig(); diff --git a/astman/Makefile b/astman/Makefile index 06bed92fa07f30ffe2cf176a386e6cdf741a847e..d3bf6ea87a3aeb43a26a80dc87931c77ca7f85b3 100755 --- a/astman/Makefile +++ b/astman/Makefile @@ -4,7 +4,7 @@ CFLAGS+=-DNO_AST_MM OSARCH=$(shell uname -s) -ifeq (${OSARCH},FreeBSD) +ifeq ($(findstring BSD,${OSARCH}),BSD) CFLAGS+=-I/usr/local/include -L/usr/local/lib endif diff --git a/channels/chan_agent.c b/channels/chan_agent.c index f91c6324b8523cbef4a4dd24d6246f0c2975c97e..bdbefe232f226f8b09382eec746e01b126d69d77 100755 --- a/channels/chan_agent.c +++ b/channels/chan_agent.c @@ -213,8 +213,8 @@ static struct agent_pvt *add_agent(char *agent, int pending) if (p) { memset(p, 0, sizeof(struct agent_pvt)); strncpy(p->agent, tmp, sizeof(p->agent) -1); - ast_mutex_init( &p->lock ); - ast_mutex_init( &p->app_lock ); + ast_mutex_init(&p->lock); + ast_mutex_init(&p->app_lock); p->owning_app = (pthread_t) -1; p->app_sleep_cond = 1; p->group = group; @@ -252,8 +252,11 @@ static int agent_cleanup(struct agent_pvt *p) ast_mutex_unlock(&p->app_lock); if (chan) ast_channel_free(chan); - if (p->dead) + if (p->dead) { + ast_mutex_destroy(&p->lock); + ast_mutex_destroy(&p->app_lock); free(p); + } return 0; } @@ -571,6 +574,8 @@ static int agent_hangup(struct ast_channel *ast) kill it later */ p->abouttograb = 0; } else if (p->dead) { + ast_mutex_destroy(&p->lock); + ast_mutex_destroy(&p->app_lock); free(p); } else { if (p->chan) { @@ -844,6 +849,8 @@ static int read_agent_config(void) /* Destroy if appropriate */ if (!p->owner) { if (!p->chan) { + ast_mutex_destroy(&p->lock); + ast_mutex_destroy(&p->app_lock); free(p); } else { /* Cause them to hang up */ @@ -1425,8 +1432,11 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode) if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Agent '%s' logged out\n", p->agent); /* If there is no owner, go ahead and kill it now */ - if (p->dead && !p->owner) + if (p->dead && !p->owner) { + ast_mutex_destroy(&p->lock); + ast_mutex_destroy(&p->app_lock); free(p); + } } else { ast_mutex_unlock(&p->lock); diff --git a/channels/chan_h323.c b/channels/chan_h323.c index e016b48123f33695e7d97b41be3cb916991fb705..622b71f17ddc99389360f4bdb80fd35f02d4d8fc 100755 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -55,7 +55,8 @@ #include <fcntl.h> #include <netdb.h> #include <sys/signal.h> -#ifdef __OpenBSD__ +#include <sys/param.h> +#if defined(BSD) #include <netinet/in_systm.h> #ifndef IPTOS_MINCOST #define IPTOS_MINCOST 0x02 @@ -186,8 +187,10 @@ static void __oh323_destroy(struct oh323_pvt *p) } if (!cur) { ast_log(LOG_WARNING, "%p is not in list?!?! \n", cur); - } else + } else { + ast_mutex_destroy(&p->lock); free(p); + } } static void oh323_destroy(struct oh323_pvt *p) @@ -1840,11 +1843,14 @@ static struct ast_rtp_protocol oh323_rtp = { set_rtp_peer: oh323_set_rtp_peer, }; - int load_module() { int res; + ast_mutex_init(&userl.lock); + ast_mutex_init(&peerl.lock); + ast_mutex_init(&aliasl.lock); + res = reload_config(); if (res) { @@ -1948,6 +1954,7 @@ int unload_module() pl = p; p = p->next; /* free associated memory */ + ast_mutex_destroy(&pl->lock); free(pl); } iflist = NULL; diff --git a/channels/chan_iax.c b/channels/chan_iax.c index b8a48fed2d1b583b5878325e01fe79c42f601d8c..055f303ec6b33042dfc6023c8444952e11a0f446 100755 --- a/channels/chan_iax.c +++ b/channels/chan_iax.c @@ -447,7 +447,7 @@ static struct iax_dpcache { struct iax_dpcache *peer; /* For linking in peers */ } *dpcache; -static ast_mutex_t dpcache_lock; +AST_MUTEX_DEFINE_STATIC(dpcache_lock); #ifdef DEBUG_SUPPORT static void showframe(struct ast_iax_frame *f, struct ast_iax_full_hdr *fhi, int rx, struct sockaddr_in *sin) @@ -5369,6 +5369,12 @@ static int __unload_module(void) int unload_module() { + int x; + for (x=0;x<AST_IAX_MAX_CALLS;x++) + ast_mutex_destroy(&iaxsl[x]); + ast_mutex_destroy(&iaxq.lock); + ast_mutex_destroy(&userl.lock); + ast_mutex_destroy(&peerl.lock); return __unload_module(); } @@ -5403,7 +5409,6 @@ int load_module(void) ast_mutex_init(&iaxq.lock); ast_mutex_init(&userl.lock); ast_mutex_init(&peerl.lock); - ast_mutex_init(&dpcache_lock); ast_cli_register(&cli_show_users); ast_cli_register(&cli_show_channels); diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index cd70a2fda1b60a74914b3a96d4cf91193fcf9d8b..ba785ce48774f2219699455eaae65d937ca844de 100755 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -507,7 +507,7 @@ static struct iax2_dpcache { struct iax2_dpcache *peer; /* For linking in peers */ } *dpcache; -static ast_mutex_t dpcache_lock; +AST_MUTEX_DEFINE_STATIC(dpcache_lock); static void iax_debug_output(const char *data) { @@ -4434,6 +4434,7 @@ static int timing_read(int *id, int fd, short events, void *cbdata) ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port)); free(drop->trunkdata); ast_mutex_unlock(&drop->lock); + ast_mutex_destroy(&drop->lock); free(drop); } @@ -6820,6 +6821,10 @@ static int __unload_module(void) int unload_module() { + ast_mutex_destroy(&iaxq.lock); + ast_mutex_destroy(&userl.lock); + ast_mutex_destroy(&peerl.lock); + ast_mutex_destroy(&waresl.lock); return __unload_module(); } @@ -6867,6 +6872,7 @@ int load_module(void) ast_mutex_init(&iaxq.lock); ast_mutex_init(&userl.lock); ast_mutex_init(&peerl.lock); + ast_mutex_init(&waresl.lock); ast_cli_register(&cli_show_users); ast_cli_register(&cli_show_channels); diff --git a/channels/chan_local.c b/channels/chan_local.c index 6421243d91572bdcc38c4752222d1001a3a58474..b4426825b575d0fdb9353aed972451277eb84346 100755 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -87,6 +87,7 @@ retrylock: /* We had a glare on the hangup. Forget all this business, return and destroy p. */ ast_mutex_unlock(&p->lock); + ast_mutex_destroy(&p->lock); free(p); return -1; } @@ -271,6 +272,7 @@ static void local_destroy(struct local_pvt *p) prev->next = cur->next; else locals = cur->next; + ast_mutex_destroy(cur); free(cur); break; } @@ -324,8 +326,10 @@ static int local_hangup(struct ast_channel *ast) } ast_mutex_unlock(&locallock); /* And destroy */ - if (!glaredetect) + if (!glaredetect) { + ast_mutex_destroy(&p->lock); free(p); + } return 0; } if (p->chan && !p->launchedpbx) @@ -366,6 +370,7 @@ static struct local_pvt *local_alloc(char *data, int format) tmp->reqformat = format; if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) { ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->context, tmp->exten); + ast_mutex_destroy(&tmp->lock); free(tmp); tmp = NULL; } else { diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index 740731eabfca2eb365a4c4e3de55393ae236bdf8..b00168eeb45fa70603441b05e43152e2f80bbb6c 100755 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -3423,15 +3423,19 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) gw->expire = -1; gw->dynamic = 0; if (ast_get_ip(&gw->addr, v->value)) { - if (!gw_reload) + if (!gw_reload) { + ast_mutex_destroy(&gw->msgs_lock); free(gw); + } return NULL; } } } else if (!strcasecmp(v->name, "defaultip")) { if (ast_get_ip(&gw->defaddr, v->value)) { - if (!gw_reload) + if (!gw_reload) { + ast_mutex_destroy(&gw->msgs_lock); free(gw); + } return NULL; } } else if (!strcasecmp(v->name, "permit") || @@ -3501,15 +3505,17 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) } if (!e) { + /* Allocate wildcard endpoint */ e = malloc(sizeof(struct mgcp_endpoint)); ep_reload = 0; } - /* Allocate wildcard endpoint */ - e = malloc(sizeof(struct mgcp_endpoint)); if (e) { if (!ep_reload) { memset(e, 0, sizeof(struct mgcp_endpoint)); + ast_mutex_init(&e->lock); + ast_mutex_init(&e->rqnt_queue_lock); + ast_mutex_init(&e->cmd_queue_lock); strncpy(e->name, v->value, sizeof(e->name) - 1); e->needaudit = 1; } @@ -3545,6 +3551,8 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) if (sub) { ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); memset(sub, 0, sizeof(struct mgcp_subchannel)); + ast_mutex_init(&sub->lock); + ast_mutex_init(&sub->cx_queue_lock); sub->parent = e; sub->id = i; snprintf(sub->txident, sizeof(sub->txident), "%08x", rand()); @@ -3594,6 +3602,9 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) if (e) { if (!ep_reload) { memset(e, 0, sizeof(struct mgcp_endpoint)); + ast_mutex_init(&e->lock); + ast_mutex_init(&e->rqnt_queue_lock); + ast_mutex_init(&e->cmd_queue_lock); strncpy(e->name, v->value, sizeof(e->name) - 1); e->needaudit = 1; } @@ -3633,8 +3644,6 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) /* ASSUME we're onhook */ e->hookstate = MGCP_ONHOOK; snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08x", rand()); - ast_mutex_init(&e->rqnt_queue_lock); - ast_mutex_init(&e->cmd_queue_lock); } for (i = 0, sub = NULL; i < MAX_SUBS; i++) { @@ -3652,13 +3661,14 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) if (!ep_reload) { ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); memset(sub, 0, sizeof(struct mgcp_subchannel)); + ast_mutex_init(&sub->lock); + ast_mutex_init(&sub->cx_queue_lock); strncpy(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic) - 1); sub->parent = e; sub->id = i; snprintf(sub->txident, sizeof(sub->txident), "%08x", rand()); sub->cxmode = MGCP_CX_INACTIVE; sub->next = e->sub; - ast_mutex_init(&sub->cx_queue_lock); e->sub = sub; } sub->nat = nat; @@ -3690,8 +3700,10 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) } if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) { ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name); - if (!gw_reload) + if (!gw_reload) { + ast_mutex_destroy(&gw->msgs_lock); free(gw); + } return NULL; } if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) @@ -3803,8 +3815,13 @@ static void destroy_endpoint(struct mgcp_endpoint *e) for (i = 0; (i < MAX_SUBS) && sub; i++) { s = sub; sub = sub->next; + ast_mutex_destroy(&s->lock); + ast_mutex_destroy(&s->cx_queue_lock); free(s); } + ast_mutex_destroy(&e->lock); + ast_mutex_destroy(&e->rqnt_queue_lock); + ast_mutex_destroy(&e->cmd_queue_lock); free(e); } @@ -4132,6 +4149,9 @@ int unload_module() pl = p; p = p->next; /* Free associated memory */ + ast_mutex_destroy(&pl->lock); + ast_mutex_destroy(&pl->rqnt_queue_lock); + ast_mutex_destroy(&pl->cmd_queue_lock); free(pl); } iflist = NULL; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index a789d89150e5db4d74535cdd91ba1e646d20a548..f7befec62e177c5dc281007c0d8e37c627a9fd4a 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2042,11 +2042,11 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg struct sip_pvt *p; p = malloc(sizeof(struct sip_pvt)); - ast_mutex_init(&p->lock); if (!p) return NULL; /* Keep track of stuff */ memset(p, 0, sizeof(struct sip_pvt)); + ast_mutex_init(&p->lock); p->initid = -1; p->autokillid = -1; p->stateid = -1; @@ -8326,6 +8326,7 @@ int unload_module() pl = p; p = p->next; /* Free associated memory */ + ast_mutex_destroy(&pl->lock); free(pl); } iflist = NULL; @@ -8338,6 +8339,9 @@ int unload_module() if (localaddr) { ast_free_ha(localaddr); } + ast_mutex_destroy(&userl.lock); + ast_mutex_destroy(&peerl.lock); + ast_mutex_destroy(®l.lock); return 0; } diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index e5189634ea89b5be7ecaaa308a497a92fb0ddd73..d73ce62b85b4a2ed78e5a3e39a046727d6c72919 100755 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -1104,6 +1104,7 @@ static struct skinny_device *build_device(char *cat, struct ast_variable *v) l = malloc(sizeof(struct skinny_line));; if (l) { memset(l, 0, sizeof(struct skinny_line)); + ast_mutex_init(&l->lock); strncpy(l->name, v->value, sizeof(l->name) - 1); /* XXX Should we check for uniqueness?? XXX */ @@ -1145,6 +1146,7 @@ static struct skinny_device *build_device(char *cat, struct ast_variable *v) if (sub) { ast_verbose(VERBOSE_PREFIX_3 "Allocating Skinny subchannel '%d' on %s@%s\n", i, l->name, d->name); memset(sub, 0, sizeof(struct skinny_subchannel)); + ast_mutex_init(&sub->lock); sub->parent = l; /* Make a call*ID */ sub->callid = callnums; @@ -2262,6 +2264,7 @@ static void destroy_session(struct skinnysession *s) sessions = cur->next; if (s->fd > -1) close(s->fd); + ast_mutex_destroy(&s->lock); free(s); } else ast_log(LOG_WARNING, "Trying to delete non-existant session %p?\n", s); @@ -2662,10 +2665,12 @@ void delete_devices(void) for (sub=l->sub;sub;) { slast = sub; sub = sub->next; + ast_mutex_destroy(&slast->lock); free(slast); } llast = l; l = l->next; + ast_mutex_destroy(&llast->lock); free(llast); } dlast = d; @@ -2758,6 +2763,7 @@ int unload_module() pl = p; p = p->next; /* Free associated memory */ + ast_mutex_destroy(&pl->lock); free(pl); } iflist = NULL; diff --git a/channels/chan_vpb.c b/channels/chan_vpb.c index 7528a0f2097cfcf58af91f21bf05b9e151eb45a6..8344ccba3d447aecc76f4d2cdadad761a6e8d0c5 100755 --- a/channels/chan_vpb.c +++ b/channels/chan_vpb.c @@ -279,8 +279,6 @@ static int vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, bridges[i].fo = fo; bridges[i].c0 = c0; bridges[i].c1 = c1; - ast_mutex_init(&bridges[i].lock); - pthread_cond_init(&bridges[i].cond, NULL); } } ast_mutex_unlock(&bridge_lock); @@ -356,8 +354,6 @@ static int vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, ast_mutex_lock(&bridge_lock); { bridges[i].inuse = 0; - ast_mutex_destroy(&bridges[i].lock); - pthread_cond_destroy(&bridges[i].cond); } ast_mutex_unlock(&bridge_lock); p0->bridge = NULL; @@ -975,8 +971,13 @@ static void mkbrd(vpb_model_t model, int echo_cancel) bridges = (vpb_bridge_t *)malloc(max_bridges * sizeof(vpb_bridge_t) ); if(!bridges) ast_log(LOG_ERROR, "Failed to initialize bridges\n"); - else + else { memset(bridges,0,max_bridges * sizeof(vpb_bridge_t)); + for(int i = 0; i < max_bridges; i++ ) { + ast_mutex_init(&bridges[i].lock); + pthread_cond_init(&bridges[i].cond, NULL); + } + } } if(!echo_cancel) { if (model==vpb_model_v4pci) { @@ -1062,6 +1063,7 @@ struct vpb_pvt *mkif(int board, int channel, int mode, float txgain, float rxgai tmp->vpb_model = vpb_model_v4pci; } + ast_mutex_init(&tmp->owner_lock); ast_mutex_init(&tmp->lock); ast_mutex_init(&tmp->record_lock); ast_mutex_init(&tmp->play_lock); @@ -2080,6 +2082,7 @@ int unload_module() p = iflist; ast_mutex_destroy(&p->lock); pthread_cancel(p->readthread); + ast_mutex_destroy(&p->owner_lock); ast_mutex_destroy(&p->record_lock); ast_mutex_destroy(&p->play_lock); ast_mutex_destroy(&p->play_dtmf_lock); @@ -2098,6 +2101,10 @@ int unload_module() memset(bridges, 0, sizeof bridges); } ast_mutex_unlock(&bridge_lock); ast_mutex_destroy(&bridge_lock); + for(int i = 0; i < max_bridges; i++ ) { + ast_mutex_destroy(&bridges[i].lock); + pthread_cond_destroy(&bridges[i].cond, NULL); + } free(bridges); return 0; diff --git a/channels/chan_zap.c b/channels/chan_zap.c index d9f88c33a4427cf6a21a958c09d50cefacf5ffb6..77547cda1c6f0eeca46b90220f12fe8b5bd588ae 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -1756,6 +1756,14 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout) return 0; } +static void destroy_zt_pvt(struct zt_pvt **pvt) +{ + struct zt_pvt *p = *pvt; + ast_mutex_destroy(&p->lock); + free(p); + *pvt = NULL; +} + static int destroy_channel(struct zt_pvt *prev, struct zt_pvt *cur, int now) { int owned = 0; @@ -1788,7 +1796,7 @@ static int destroy_channel(struct zt_pvt *prev, struct zt_pvt *cur, int now) if (cur->subs[SUB_REAL].zfd > -1) { zt_close(cur->subs[SUB_REAL].zfd); } - free(cur); + destroy_zt_pvt(&cur); } } else { if (prev) { @@ -1807,7 +1815,7 @@ static int destroy_channel(struct zt_pvt *prev, struct zt_pvt *cur, int now) if (cur->subs[SUB_REAL].zfd > -1) { zt_close(cur->subs[SUB_REAL].zfd); } - free(cur); + destroy_zt_pvt(&cur); } return 0; } @@ -5751,10 +5759,11 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p tmp = (struct zt_pvt*)malloc(sizeof(struct zt_pvt)); if (!tmp) { ast_log(LOG_ERROR, "MALLOC FAILED\n"); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } memset(tmp, 0, sizeof(struct zt_pvt)); + ast_mutex_init(&tmp->lock); ifcount++; for (x=0;x<3;x++) tmp->subs[x].zfd = -1; @@ -5811,20 +5820,19 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p /* Allocate a zapata structure */ if (tmp->subs[SUB_REAL].zfd < 0) { ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } memset(&p, 0, sizeof(p)); res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &p); if (res < 0) { ast_log(LOG_ERROR, "Unable to get parameters\n"); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } if (p.sigtype != (signalling & 0x3ffff)) { ast_log(LOG_ERROR, "Signalling requested is %s but line is in %s signalling\n", sig2str(signalling), sig2str(p.sigtype)); - free(tmp); - tmp = NULL; + destroy_zt_pvt(&tmp); return tmp; } if (here) { @@ -5855,18 +5863,18 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p offset = 0; if ((signalling == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &offset)) { ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } if (span >= NUM_SPANS) { ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } else { si.spanno = 0; if (ioctl(tmp->subs[SUB_REAL].zfd,ZT_SPANSTAT,&si) == -1) { ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } /* Store the logical span first based upon the real span */ @@ -5874,7 +5882,7 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p pri_resolve_span(&span, channel, (channel - p.chanpos), &si); if (span < 0) { ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } if (signalling == SIG_PRI) @@ -5895,43 +5903,43 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p if (!matchesdchan) { if (pris[span].nodetype && (pris[span].nodetype != pritype)) { ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } if ((pris[span].dialplan) && (pris[span].dialplan != dialplan)) { ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, pri_plan2str(pris[span].dialplan)); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, idledial)) { ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, idledial); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, idleext)) { ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, idleext); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } if (pris[span].minunused && (pris[span].minunused != minunused)) { ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, minunused); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } if (pris[span].minidle && (pris[span].minidle != minidle)) { ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, minidle); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } if (pris[span].numchans >= MAX_CHANNELS) { ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, pris[span].trunkgroup); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } pris[span].nodetype = pritype; @@ -5949,7 +5957,7 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p tmp->call = NULL; } else { ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } } @@ -5968,7 +5976,7 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p if (!tmp->r2) { ast_log(LOG_WARNING, "Unable to create r2 call :(\n"); zt_close(tmp->subs[SUB_REAL].zfd); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } } else { @@ -6021,7 +6029,7 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_SET_PARAMS, &p); if (res < 0) { ast_log(LOG_ERROR, "Unable to set parameters\n"); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } } @@ -6081,7 +6089,6 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p tmp->propconfno = -1; } tmp->transfer = transfer; - ast_mutex_init(&tmp->lock); strncpy(tmp->defcontext,context,sizeof(tmp->defcontext)-1); strncpy(tmp->language, language, sizeof(tmp->language)-1); strncpy(tmp->musicclass, musicclass, sizeof(tmp->musicclass)-1); @@ -6117,7 +6124,7 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p memset(&si, 0, sizeof(si)); if (ioctl(tmp->subs[SUB_REAL].zfd,ZT_SPANSTAT,&si) == -1) { ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); - free(tmp); + destroy_zt_pvt(&tmp); return NULL; } if (si.alarms) tmp->inalarm = 1; @@ -6222,11 +6229,12 @@ static struct zt_pvt *chandup(struct zt_pvt *src) p = malloc(sizeof(struct zt_pvt)); if (p) { memcpy(p, src, sizeof(struct zt_pvt)); + ast_mutex_init(&p->lock); p->subs[SUB_REAL].zfd = zt_open("/dev/zap/pseudo"); /* Allocate a zapata structure */ if (p->subs[SUB_REAL].zfd < 0) { ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); - free(p); + destroy_zt_pvt(&p); return NULL; } res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_BUFINFO, &bi); @@ -8280,8 +8288,8 @@ static int __unload_module(void) p = p->next; x++; /* Free associated memory */ - if(p) - free(pl); + if(pl) + destroy_zt_pvt(&pl); ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x); } iflist = NULL; @@ -8302,6 +8310,11 @@ static int __unload_module(void) int unload_module() { +#ifdef ZAPATA_PRI + int y; + for (y=0;y<NUM_SPANS;y++) + ast_mutex_destroy(&pris[y].lock); +#endif return __unload_module(); } @@ -8922,6 +8935,7 @@ int load_module(void) int y,i; memset(pris, 0, sizeof(pris)); for (y=0;y<NUM_SPANS;y++) { + ast_mutex_init(&pris[y].lock); pris[y].offset = -1; pris[y].master = AST_PTHREADT_NULL; for (i=0;i<NUM_DCHANS;i++) @@ -9028,9 +9042,13 @@ static int reload_zt(void) #if 0 #ifdef ZAPATA_PRI - memset(pris, 0, sizeof(pris)); for (y=0;y<NUM_SPANS;y++) + ast_mutex_destroy(&pris[y]->lock); + memset(pris, 0, sizeof(pris)); + for (y=0;y<NUM_SPANS;y++) { + ast_mutex_init(&pris[y]->lock); pris[y].fd = -1; + } #endif #endif /* 0 */ diff --git a/channels/h323/INSTALL.openh323 b/channels/h323/INSTALL.openh323 index 426e767010e00184f6a3c02685e6c37d10047c52..f46c3790585c74a65fd8005725e8c5d99b4918c4 100755 --- a/channels/h323/INSTALL.openh323 +++ b/channels/h323/INSTALL.openh323 @@ -6,3 +6,13 @@ You only need to do 'make opt'. Anything else you will be simply waisting time a Also, you will notice they never tell you to 'make install' so don't do it. +On FreeBSD, the Makefiles are configured to +locate the compiled openh323 port, if it has +been built. Here is one way to build +openh323 and ptlib on such that the Makefiles +find it: + # cd /usr/ports/net/openh323 + # make +It is not necessary to install the port. The +asterisk makefiles do not use any files +installed by the port. diff --git a/channels/h323/Makefile b/channels/h323/Makefile index 56cd61974fcf16378eaab65b4a3505ab5efbded5..fa9c8ea11f79d4f1c3826e9f06257f1871768acd 100755 --- a/channels/h323/Makefile +++ b/channels/h323/Makefile @@ -19,8 +19,15 @@ endif # # This needs to be updated to deal with more than just little endian machines # -CFLAGS += -march=$(shell uname -m) -DPBYTE_ORDER=PLITTLE_ENDIAN +OSARCH=$(shell uname -s) +ifneq (${OSARCH},FreeBSD) +CFLAGS += -march=$(shell uname -m) +endif +CFLAGS += -DPBYTE_ORDER=PLITTLE_ENDIAN +ifeq (${OSARCH},Linux) +LDLIBS+=-ldl +endif ############################################# # @@ -38,16 +45,22 @@ CFLAGS += -march=$(shell uname -m) -DPBYTE_ORDER=PLITTLE_ENDIAN # Pre Janus release directives CFLAGS += -DNDEBUG -DDO_CRASH -DDEBUG_THREADS -CFLAGS += -pipe -Wall -fPIC -Wmissing-prototypes -Wmissing-declarations +CFLAGS += -pipe -Wall -fPIC ifeq (${OSARCH},Linux) CFLAGS += -DP_LINUX +LIBS+=-lpthread +endif +ifeq ($(findstring BSD,${OSARCH}),BSD) +CFLAGS += -pthread endif CFLAGS += -D_REENTRANT -D_GNU_SOURCE CFLAGS += -DP_HAS_SEMAPHORES -DP_SSL -DP_PTHREADS CFLAGS += -DPHAS_TEMPLATES -DPTRACING -DP_USE_PRAGMA CFLAGS += -I../../include CFLAGS += -I$(PWLIBDIR)/include/ptlib/unix -I$(PWLIBDIR)/include -CFLAGS += -I$(OPENH323DIR)/include -Wno-missing-prototypes -Wno-missing-declarations +CFLAGS += -I$(OPENH323DIR)/include +CFLAGS += -Wno-missing-prototypes -Wno-missing-declarations +LIBS+= -lcrypto -lssl -lexpat all: libchanh323.a @@ -59,19 +72,19 @@ samples: ast_h323.o: ast_h323.cpp - g++ -g -c -fno-rtti -o $@ $(CFLAGS) $< + $(CXX) -g -c -fno-rtti -o $@ $(CFLAGS) $< libchanh323.a: ast_h323.o ar cr libchanh323.a ast_h323.o chan_h323.so: - g++ -g -shared -Xlinker -x -o chan_h323.so chan_h323.o ast_h323.o -L$(PWLIBDIR)/lib -lpt_linux_x86_r -L$(OPENH323DIR)/lib -lh323_linux_x86_r -L/usr/lib -lpthread -ldl -lcrypto -lssl -lexpat + $(CXX) -g -shared -Xlinker -x -o chan_h323.so chan_h323.o ast_h323.o -L$(PWLIBDIR)/lib -lpt_linux_x86_r -L$(OPENH323DIR)/lib -lh323_linux_x86_r -L/usr/lib $(CHANH323LIB) chan_h323_d.so: chan_h323.o ast_h323.o - g++ -shared -Xlinker -x -o chan_h323.so chan_h323.o ast_h323.o -L$(PWLIBDIR)/lib -lpt_linux_x86_d -L$(OPENH323DIR)/lib -lh323_linux_x86_d -L/usr/lib -lpthread -ldl -lcrypto -lssl -lexpat + $(CXX) -shared -Xlinker -x -o chan_h323.so chan_h323.o ast_h323.o -L$(PWLIBDIR)/lib -lpt_linux_x86_d -L$(OPENH323DIR)/lib -lh323_linux_x86_d -L/usr/lib $(CHANH323LIB) chan_h323_s.so: chan_h323.o ast_h323.o - g++ -shared -Xlinker -x -o chan_h323.so chan_h323.o ast_h323.o -L$(PWLIBDIR)/lib -lpt_linux_x86_r_s -L$(OPENH323DIR)/lib -lh323_linux_x86_r_s -L/usr/lib -lpthread -ldl -lcrypto -lssl -lexpat + $(CXX) -shared -Xlinker -x -o chan_h323.so chan_h323.o ast_h323.o -L$(PWLIBDIR)/lib -lpt_linux_x86_r_s -L$(OPENH323DIR)/lib -lh323_linux_x86_r_s -L/usr/lib $(CHANH323LIB) clean: rm -f *.o *.so core.* libchanh323.a diff --git a/cli.c b/cli.c index 421617d0107a26eead8204fc5b5cba4afd968196..6543a0bf0524c829ed436cd64d57aa8e6c3a812d 100755 --- a/cli.c +++ b/cli.c @@ -181,8 +181,8 @@ static char *format_uptimestr(time_t timeval) char timestr[256]; int pos = 0; #define SECOND (1) -#define MIN (SECOND*60) -#define HOUR (MIN*60) +#define MINUTE (SECOND*60) +#define HOUR (MINUTE*60) #define DAY (HOUR*24) #define WEEK (DAY*7) #define YEAR (DAY*365) @@ -222,9 +222,9 @@ static char *format_uptimestr(time_t timeval) else pos += sprintf(timestr + pos, "1 hour, "); } - if (timeval > MIN) { - mins = (timeval / MIN); - timeval -= (mins * MIN); + if (timeval > MINUTE) { + mins = (timeval / MINUTE); + timeval -= (mins * MINUTE); if (mins > 1) pos += sprintf(timestr + pos, "%d minutes, ", mins); else if (mins > 0) diff --git a/codecs/gsm/Makefile b/codecs/gsm/Makefile index 1cfa939e1dd2ad9dd10915916c243505b456811d..9105ef4f395d938473c428467f9d758d866377f8 100755 --- a/codecs/gsm/Makefile +++ b/codecs/gsm/Makefile @@ -64,8 +64,8 @@ PG = # CC = /usr/lang/acc # CCFLAGS = -c -O -CC = gcc $(OPTIMIZE) -fomit-frame-pointer -CCFLAGS += -c -DNeedFunctionPrototypes=1 -funroll-loops -fPIC +CC ?= gcc +CCFLAGS += -c -DNeedFunctionPrototypes=1 -funroll-loops -fPIC $(OPTIMIZE) -fomit-frame-pointer LD = $(CC) @@ -150,7 +150,7 @@ INC = $(ROOT)/inc DEBUG = -DNDEBUG ######### Remove -DNDEBUG to enable assertions. -CFLAGS = $(PG) $(CCFLAGS) $(SASR) $(DEBUG) $(MULHACK) $(FAST) \ +CFLAGS += $(PG) $(CCFLAGS) $(SASR) $(DEBUG) $(MULHACK) $(FAST) \ $(LTP_CUT) $(WAV49) $(K6OPT) $(CCINC) -I$(INC) ######### It's $(CC) $(CFLAGS) diff --git a/codecs/lpc10/Makefile b/codecs/lpc10/Makefile index af8d907f640e189b23d25859255fac406562d3bc..cd1e973ef7d04aa1e4b1cedbaa7664d94d680963 100755 --- a/codecs/lpc10/Makefile +++ b/codecs/lpc10/Makefile @@ -3,7 +3,7 @@ # # default C compiler -CC= gcc +CC?= gcc # # These definitions for CFLAGS and LIB_TARGET_DIR are used when one @@ -22,11 +22,12 @@ LIB_TARGET_DIR = . # WARNINGS = -Wall -Wno-comment -Wno-error -CFLAGS = $(OPTIMIZE) -I$(LIB_TARGET_DIR) $(WARNINGS) -fPIC +CFLAGS += $(OPTIMIZE) -I$(LIB_TARGET_DIR) $(WARNINGS) -fPIC #CFLAGS+= $(shell if uname -m | grep -q 86; then echo "-mpentium" ; fi) #fix for PPC processors and ALPHA too ifneq ($(OSARCH),Darwin) +ifneq ($(findstring BSD,${OSARCH}),BSD) ifneq ($(PROC),ppc) ifneq ($(PROC),x86_64) ifneq ($(PROC),alpha) @@ -35,6 +36,7 @@ endif endif endif endif +endif LIB = $(LIB_TARGET_DIR)/liblpc10.a diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h index 309c7ab82b365cece445e07765975ef3e1c5528f..e1c9388df65e2b7646806359911d40acf55d53e6 100755 --- a/include/asterisk/lock.h +++ b/include/asterisk/lock.h @@ -16,6 +16,8 @@ #include <pthread.h> #include <netdb.h> +#include <time.h> +#include <sys/param.h> #define AST_PTHREADT_NULL (pthread_t) -1 #define AST_PTHREADT_STOP (pthread_t) -2 @@ -28,13 +30,23 @@ 0x20 } } #endif -#ifdef __FreeBSD__ +#ifdef BSD #ifdef __GNUC__ #define AST_MUTEX_INIT_W_CONSTRUCTORS #else #define AST_MUTEX_INIT_ON_FIRST_USE #endif -#endif /* __FreeBSD__ */ +#endif /* BSD */ + +/* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes + and will not run without them. */ +#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +#define PTHREAD_MUTEX_INIT_VALUE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP +#else +#define PTHREAD_MUTEX_INIT_VALUE PTHREAD_MUTEX_INITIALIZER +#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE +#endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */ #ifdef DEBUG_THREADS @@ -47,15 +59,7 @@ #include <stdio.h> #include <unistd.h> -/* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes - and will not run without them. */ -#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP -#define AST_MUTEX_INIT_VAULE { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, NULL, 0, NULL, 0 } -#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP -#else -#define AST_MUTEX_INIT_VAULE { PTHREAD_MUTEX_INITIALIZER, NULL, 0, NULL, 0 } -#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE -#endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */ +#define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, NULL, 0, NULL, 0 } struct ast_mutex_info { pthread_mutex_t mutex; @@ -67,28 +71,88 @@ struct ast_mutex_info { typedef struct ast_mutex_info ast_mutex_t; -static inline int ast_pthread_mutex_init(ast_mutex_t *t, pthread_mutexattr_t *attr) +static inline int __ast_pthread_mutex_init_attr(char *filename, int lineno, char *func, + char* mutex_name, ast_mutex_t *t, + pthread_mutexattr_t *attr) { - t->file = NULL; - t->lineno = 0; - t->func = 0; +#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS + if((t->mutex) != ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) { + fprintf(stderr, "%s line %d (%s): Error: mutex '%s' is already initialized.\n", + filename, lineno, func, mutex_name); + fprintf(stderr, "%s line %d (%s): Error: previously initialization of mutex '%s'.\n", + t->file, t->lineno, t->func, mutex_name); +#ifdef THREAD_CRASH + DO_THREAD_CRASH; +#endif + return 0; + } +#endif + t->file = filename; + t->lineno = lineno; + t->func = func; t->thread = 0; return pthread_mutex_init(&t->mutex, attr); } -static inline int ast_mutex_init(ast_mutex_t *t) +static inline int __ast_pthread_mutex_init(char *filename, int lineno, char *func, + char* mutex_name, ast_mutex_t *t) { static pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, AST_MUTEX_KIND); - return ast_pthread_mutex_init(t, &attr); + return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr); } +#define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex) +#define ast_pthread_mutex_init(pmutex,attr) __ast_pthread_mutex_init_attr(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex, attr) + +static inline int __ast_pthread_mutex_destroy(char *filename, int lineno, char *func, + char* mutex_name, ast_mutex_t *t) +{ + int res; +#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS + if((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) { + fprintf(stderr, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n", + filename, lineno, func, mutex_name); + } +#endif + res = pthread_mutex_trylock(&t->mutex); + switch( res ) { + case 0: + pthread_mutex_unlock(&t->mutex); + break; + case EINVAL: + fprintf(stderr, "%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n", + filename, lineno, func, mutex_name); + break; + case EBUSY: + fprintf(stderr, "%s line %d (%s): Error: attemp to destroy locked mutex '%s'.\n", + filename, lineno, func, mutex_name); + fprintf(stderr, "%s line %d (%s): Error: '%s' was locked here.\n", + t->file, t->lineno, t->func, mutex_name); + break; + } + res = pthread_mutex_destroy(&t->mutex); + if (res) + fprintf(stderr, "%s line %d (%s): Error destroying mutex: %s\n", + filename, lineno, func, strerror(res)); +#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP + else + t->mutex = PTHREAD_MUTEX_INIT_VALUE; +#endif + t->file = filename; + t->lineno = lineno; + t->func = func; + return res; +} + +#define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a) + #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope - constrictors/destructors to create/destroy mutexes. */ + constrictors/destructors to create/destroy mutexes. */ #define __AST_MUTEX_DEFINE(scope,mutex) \ - scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE; \ + scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \ static void __attribute__ ((constructor)) init_##mutex(void) \ { \ ast_mutex_init(&mutex); \ @@ -97,24 +161,54 @@ static void __attribute__ ((destructor)) fini_##mutex(void) \ { \ ast_mutex_destroy(&mutex); \ } -#elif defined(AST_MUTEX_INIT_ON_FIRST_USE) || !defined(AST_MUTEX_INIT_W_CONSTRUCTORS) +#elif defined(AST_MUTEX_INIT_ON_FIRST_USE) /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on first use. The performance impact on FreeBSD should be small since the pthreads library does this itself to initialize errror checking (defaulty type) mutexes. If nither is defined, the pthreads librariy does the initialization itself on first use. */ #define __AST_MUTEX_DEFINE(scope,mutex) \ - scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE + scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE +#else /* AST_MUTEX_INIT_W_CONSTRUCTORS */ +/* By default, use static initialization of mutexes.*/ +#define __AST_MUTEX_DEFINE(scope,mutex) \ + scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ -static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *func, ast_mutex_t *t) + + +static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *func, + char* mutex_name, ast_mutex_t *t) { int res; -#ifdef AST_MUTEX_INIT_ON_FIRST_USE - if(*t->mutex == (ast_mutex_t)AST_MUTEX_KIND) - ast_mutex_init(t->mutex); +#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) + if((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) { +#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS + fprintf(stderr, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n", + filename, lineno, func, mutex_name); #endif - res = pthread_mutex_lock(&t->mutex); + ast_mutex_init(t); + } +#endif /* definded(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */ +#ifdef DETECT_DEADLOCKS + { + time_t seconds seconds = time(NULL); + do { + res = pthread_mutex_trylock(&t->mutex); + if(res == EBUSY) { + if((time(NULL) - seconds) % 5) { + fprintf(stderr, "%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n", + filename, lineno, func, (time(NULL) - seconds), mutex_name); + fprintf(stderr, "%s line %d (%s): '%s' was locked here.\n", + t->file, t->lineno, t->func, mutex_name); + } + usleep(200); + } + } while (res == EBUSY); + } +#else + res = pthread_mutex_lock(&t->mutex); +#endif /* DETECT_DEADLOCKS */ if (!res) { t->file = filename; t->lineno = lineno; @@ -130,14 +224,21 @@ static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *fun return res; } -#define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a) +#define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a) -static inline int __ast_pthread_mutex_trylock(char *filename, int lineno, char *func, ast_mutex_t *t) { +static inline int __ast_pthread_mutex_trylock(char *filename, int lineno, char *func, + char* mutex_name, ast_mutex_t *t) +{ int res; -#ifdef AST_MUTEX_INIT_ON_FIRST_USE - if(*t->mutex == (ast_mutex_t)AST_MUTEX_KIND) - ast_mutex_init(t->mutex); +#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) + if((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) { +#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS + fprintf(stderr, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n", + filename, lineno, func, mutex_name); #endif + ast_mutex_init(t); + } +#endif /* definded(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */ res = pthread_mutex_trylock(&t->mutex); if (!res) { t->file = filename; @@ -148,10 +249,17 @@ static inline int __ast_pthread_mutex_trylock(char *filename, int lineno, char * return res; } -#define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a) +#define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a) -static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *func, ast_mutex_t *t) { +static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *func, + char* mutex_name, ast_mutex_t *t) { int res; +#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS + if((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) { + fprintf(stderr, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n", + filename, lineno, func, mutex_name); + } +#endif /* Assumes lock is actually held */ t->file = NULL; t->lineno = 0; @@ -168,23 +276,7 @@ static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *f return res; } -#define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a) - -static inline int __ast_pthread_mutex_destroy(char *filename, int lineno, char *func, ast_mutex_t *t) -{ - int res; - t->file = NULL; - t->lineno = 0; - t->func = NULL; - t->thread = 0; - res = pthread_mutex_destroy(&t->mutex); - if (res) - fprintf(stderr, "%s line %d (%s): Error destroying mutex: %s\n", - filename, lineno, func, strerror(res)); - return res; -} - -#define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, a) +#define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a) #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock @@ -195,15 +287,9 @@ static inline int __ast_pthread_mutex_destroy(char *filename, int lineno, char * #else /* DEBUG_THREADS */ -/* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes - and will not run without them. */ -#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP -#define AST_MUTEX_INIT_VAULE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP -#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP -#else -#define AST_MUTEX_INIT_VAULE PTHREAD_MUTEX_INITIALIZER -#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE -#endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */ + +#define AST_MUTEX_INIT_VALUE PTHREAD_MUTEX_INIT_VALUE + typedef pthread_mutex_t ast_mutex_t; @@ -222,7 +308,7 @@ static inline int ast_mutex_init(ast_mutex_t *pmutex) /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope constrictors/destructors to create/destroy mutexes. */ #define __AST_MUTEX_DEFINE(scope,mutex) \ - scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE; \ + scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \ static void __attribute__ ((constructor)) init_##mutex(void) \ { \ ast_mutex_init(&mutex); \ @@ -241,7 +327,7 @@ static void __attribute__ ((destructor)) fini_##mutex(void) \ the pthreads library does this itself to initialize errror checking (defaulty type) mutexes.*/ #define __AST_MUTEX_DEFINE(scope,mutex) \ - scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE + scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE static inline int ast_mutex_lock(ast_mutex_t *pmutex) { @@ -258,7 +344,7 @@ static inline int ast_mutex_trylock(ast_mutex_t *pmutex) #else /* By default, use static initialization of mutexes.*/ #define __AST_MUTEX_DEFINE(scope,mutex) \ - scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE + scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE #define ast_mutex_lock(pmutex) pthread_mutex_lock(pmutex) #define ast_mutex_trylock(pmutex) pthread_mutex_trylock(pmutex) #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ @@ -270,6 +356,7 @@ static inline int ast_mutex_trylock(ast_mutex_t *pmutex) #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__ + #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__ #endif diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h index 686f4cb1e84cf16d4737458f597482733ccd0e4c..16212a038d60d47704c2f7c3db5143b651cbc80e 100755 --- a/include/asterisk/utils.h +++ b/include/asterisk/utils.h @@ -26,4 +26,6 @@ struct ast_hostent { extern struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp); +extern int test_for_thread_safety(void); + #endif diff --git a/include/asterisk/vmodem.h b/include/asterisk/vmodem.h index a2651bdd4737f7127a65447de59e9aef05fd8f70..69886154b0b5bbbb16998ab7af0308b8680bb57d 100755 --- a/include/asterisk/vmodem.h +++ b/include/asterisk/vmodem.h @@ -5,7 +5,7 @@ * * Copyright (C) 1999, Mark Spencer * - * Mark Spencer <markster@linux-support.net> + * Mark Spencer <markster@digium.com> * * This program is free software, distributed under the terms of * the GNU General Public License diff --git a/manager.c b/manager.c index f5055d124478455484fb6f4d40d6c2bef407ab9c..e16bdf8b3eafce2b6ac8161d5392e22b98ebf005 100755 --- a/manager.c +++ b/manager.c @@ -220,6 +220,7 @@ static void destroy_session(struct mansession *s) sessions = cur->next; if (s->fd > -1) close(s->fd); + ast_mutex_destroy(&s->lock); free(s); } else ast_log(LOG_WARNING, "Trying to delete non-existant session %p?\n", s); diff --git a/pbx.c b/pbx.c index 05f3dd20c3918404d857802a10fdfa5c453455d2..697c016f2dc2e4fefdbbae5491419c2b594762f5 100755 --- a/pbx.c +++ b/pbx.c @@ -4173,6 +4173,7 @@ void __ast_context_destroy(struct ast_context *con, char *registrar) e = e->next; destroy_exten(el); } + ast_mutex_destroy(&tmp->lock); free(tmp); if (!con) { /* Might need to get another one -- restart */ diff --git a/sched.c b/sched.c index b8c4940150840545c348592d0f688f7146feec0b..48417ef7106d0832af26b20ce78bbd14042b06b3 100755 --- a/sched.c +++ b/sched.c @@ -22,6 +22,7 @@ #include <sys/time.h> #include <unistd.h> #include <pthread.h> +#include <string.h> #include <asterisk/sched.h> #include <asterisk/logger.h> @@ -63,6 +64,7 @@ struct sched_context *sched_context_create(void) struct sched_context *tmp; tmp = malloc(sizeof(struct sched_context)); if (tmp) { + memset(tmp, 0, sizeof(struct sched_context)); ast_mutex_init(&tmp->lock); tmp->eventcnt = 1; tmp->schedcnt = 0; @@ -97,6 +99,7 @@ void sched_context_destroy(struct sched_context *con) } /* And the context */ ast_mutex_unlock(&con->lock); + ast_mutex_destroy(&con->lock); free(con); } diff --git a/utils.c b/utils.c index f61a9480b999427bb923a8b7806bab151e6c8b88..d65f2a8e53079a2561c25885cb09cde6975a4964 100755 --- a/utils.c +++ b/utils.c @@ -11,6 +11,8 @@ #include <ctype.h> #include <string.h> +#include <unistd.h> +#include <pthread.h> #include <asterisk/lock.h> #include <asterisk/utils.h> @@ -22,9 +24,9 @@ AST_MUTEX_DEFINE_STATIC(__mutex); -int gethostbyname_r (const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, - int *h_errnop) +static int gethostbyname_r (const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, + int *h_errnop) { int hsave; struct hostent *ph; @@ -143,3 +145,60 @@ struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp) return NULL; return &hp->hp; } + + +/* This is a regression test for recursive mutexes. + test_for_thread_safety() will return 0 if recursive mutex locks are + working properly, and non-zero if they are not working properly. */ + +AST_MUTEX_DEFINE_STATIC(test_lock); +AST_MUTEX_DEFINE_STATIC(test_lock2); +static pthread_t test_thread; +static int lock_count = 0; +static int test_errors = 0; + +static void *test_thread_body(void *data) +{ + ast_mutex_lock(&test_lock); + lock_count += 10; + if(lock_count != 10) test_errors++; + ast_mutex_lock(&test_lock); + lock_count += 10; + if(lock_count != 20) test_errors++; + ast_mutex_lock(&test_lock2); + ast_mutex_unlock(&test_lock); + lock_count -= 10; + if(lock_count != 10) test_errors++; + ast_mutex_unlock(&test_lock); + lock_count -= 10; + ast_mutex_unlock(&test_lock2); + if(lock_count != 0) test_errors++; + return NULL; +} + +int test_for_thread_safety(void) +{ + ast_mutex_lock(&test_lock2); + ast_mutex_lock(&test_lock); + lock_count += 1; + ast_mutex_lock(&test_lock); + lock_count += 1; + pthread_create(&test_thread, NULL, test_thread_body, NULL); + pthread_yield(); + usleep(100); + if(lock_count != 2) test_errors++; + ast_mutex_unlock(&test_lock); + lock_count -= 1; + pthread_yield(); + usleep(100); + if(lock_count != 1) test_errors++; + ast_mutex_unlock(&test_lock); + lock_count -= 1; + if(lock_count != 0) test_errors++; + ast_mutex_unlock(&test_lock2); + pthread_yield(); + usleep(100); + if(lock_count != 0) test_errors++; + pthread_join(test_thread, NULL); + return(test_errors); /* return 0 on success. */ +}