[asterisk-commits] bbryant: trunk r123546 - in /trunk: apps/ channels/ include/asterisk/ main/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Jun 17 16:46:57 CDT 2008
Author: bbryant
Date: Tue Jun 17 16:46:57 2008
New Revision: 123546
URL: http://svn.digium.com/view/asterisk?view=rev&rev=123546
Log:
Updates all usages of ast_tcptls_session_instance to be managed by reference counts so that they only get destroyed when all threads are done using
them, and memory does not get free'd causing strange issues with SIP.
This code was originally written by russellb in the team/group/issue_11972/ branch.
Modified:
trunk/apps/app_externalivr.c
trunk/channels/chan_sip.c
trunk/include/asterisk/tcptls.h
trunk/main/astobj2.c
trunk/main/http.c
trunk/main/manager.c
trunk/main/tcptls.c
Modified: trunk/apps/app_externalivr.c
URL: http://svn.digium.com/view/asterisk/trunk/apps/app_externalivr.c?view=diff&rev=123546&r1=123545&r2=123546
==============================================================================
--- trunk/apps/app_externalivr.c (original)
+++ trunk/apps/app_externalivr.c Tue Jun 17 16:46:57 2008
@@ -515,8 +515,7 @@
if (child_stderr[1])
close(child_stderr[1]);
if (ser) {
- fclose(ser->f);
- ast_tcptls_session_instance_destroy(ser);
+ ao2_ref(ser, -1);
}
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list)))
ast_free(entry);
Modified: trunk/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_sip.c?view=diff&rev=123546&r1=123545&r2=123546
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Tue Jun 17 16:46:57 2008
@@ -798,7 +798,6 @@
/*!< The SIP socket definition */
struct sip_socket {
- ast_mutex_t *lock;
enum sip_transport type;
int fd;
uint16_t port;
@@ -844,6 +843,7 @@
char *header[SIP_MAX_HEADERS];
char *line[SIP_MAX_LINES];
struct ast_str *data;
+ /* XXX Do we need to unref socket.ser when the request goes away? */
struct sip_socket socket; /*!< The socket used for this request */
};
@@ -2291,14 +2291,6 @@
static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *ser);
-static void *sip_tcp_helper_thread(void *data)
-{
- struct sip_pvt *pvt = data;
- struct ast_tcptls_session_instance *ser = pvt->socket.ser;
-
- return _sip_tcp_helper_thread(pvt, ser);
-}
-
static void *sip_tcp_worker_fn(void *data)
{
struct ast_tcptls_session_instance *ser = data;
@@ -2312,7 +2304,7 @@
int res, cl;
struct sip_request req = { 0, } , reqcpy = { 0, };
struct sip_threadinfo *me;
- char buf[1024];
+ char buf[1024] = "";
me = ast_calloc(1, sizeof(*me));
@@ -2330,12 +2322,6 @@
AST_LIST_INSERT_TAIL(&threadl, me, list);
AST_LIST_UNLOCK(&threadl);
- req.socket.lock = ast_calloc(1, sizeof(*req.socket.lock));
-
- if (!req.socket.lock)
- goto cleanup;
-
- ast_mutex_init(req.socket.lock);
if (!(req.data = ast_str_create(SIP_MIN_PACKET)))
goto cleanup;
if (!(reqcpy.data = ast_str_create(SIP_MIN_PACKET)))
@@ -2364,14 +2350,12 @@
/* Read in headers one line at a time */
while (req.len < 4 || strncmp((char *)&req.data->str + req.len - 4, "\r\n\r\n", 4)) {
- if (req.socket.lock)
- ast_mutex_lock(req.socket.lock);
+ ast_mutex_lock(&ser->lock);
if (!fgets(buf, sizeof(buf), ser->f)) {
- ast_mutex_unlock(req.socket.lock);
+ ast_mutex_unlock(&ser->lock);
goto cleanup;
}
- if (req.socket.lock)
- ast_mutex_unlock(req.socket.lock);
+ ast_mutex_unlock(&ser->lock);
if (me->stop)
goto cleanup;
ast_str_append(&req.data, 0, "%s", buf);
@@ -2381,12 +2365,12 @@
parse_request(&reqcpy);
if (sscanf(get_header(&reqcpy, "Content-Length"), "%d", &cl)) {
while (cl > 0) {
- if (req.socket.lock)
- ast_mutex_lock(req.socket.lock);
- if (!fread(buf, (cl < sizeof(buf)) ? cl : sizeof(buf), 1, ser->f))
+ ast_mutex_lock(&ser->lock);
+ if (!fread(buf, (cl < sizeof(buf)) ? cl : sizeof(buf), 1, ser->f)) {
+ ast_mutex_unlock(&ser->lock);
goto cleanup;
- if (req.socket.lock)
- ast_mutex_unlock(req.socket.lock);
+ }
+ ast_mutex_unlock(&ser->lock);
if (me->stop)
goto cleanup;
cl -= strlen(buf);
@@ -2405,7 +2389,8 @@
ast_free(me);
cleanup2:
fclose(ser->f);
- ser = ast_tcptls_session_instance_destroy(ser);
+ ser->f = NULL;
+ ser->fd = -1;
if (reqcpy.data)
ast_free(reqcpy.data);
if (req.data) {
@@ -2414,11 +2399,8 @@
}
- if (req.socket.lock) {
- ast_mutex_destroy(req.socket.lock);
- ast_free(req.socket.lock);
- req.socket.lock = NULL;
- }
+ ao2_ref(ser, -1);
+ ser = NULL;
return NULL;
}
@@ -2761,8 +2743,8 @@
if (sip_prepare_socket(p) < 0)
return XMIT_ERROR;
- if (p->socket.lock)
- ast_mutex_lock(p->socket.lock);
+ if (p->socket.ser)
+ ast_mutex_lock(&p->socket.ser->lock);
if (p->socket.type & SIP_TRANSPORT_UDP)
res = sendto(p->socket.fd, data->str, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
@@ -2773,8 +2755,8 @@
ast_debug(1, "No p->socket.ser->f len=%d\n", len);
}
- if (p->socket.lock)
- ast_mutex_unlock(p->socket.lock);
+ if (p->socket.ser)
+ ast_mutex_unlock(&p->socket.ser->lock);
if (res == -1) {
switch (errno) {
@@ -3780,6 +3762,11 @@
if (peer->dnsmgr)
ast_dnsmgr_release(peer->dnsmgr);
clear_peer_mailboxes(peer);
+
+ if (peer->socket.ser) {
+ ao2_ref(peer->socket.ser, -1);
+ peer->socket.ser = NULL;
+ }
}
/*! \brief Update peer data in database (if used) */
@@ -4201,6 +4188,20 @@
}
}
+static void copy_socket_data(struct sip_socket *to_sock, const struct sip_socket *from_sock)
+{
+ if (to_sock->ser) {
+ ao2_ref(to_sock->ser, -1);
+ to_sock->ser = NULL;
+ }
+
+ if (from_sock->ser) {
+ ao2_ref(from_sock->ser, +1);
+ }
+
+ *to_sock = *from_sock;
+}
+
/*! \brief Create address structure from peer reference.
* This function copies data from peer to the dialog, so we don't have to look up the peer
* again from memory or database during the life time of the dialog.
@@ -4210,7 +4211,7 @@
*/
static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
{
- dialog->socket = peer->socket;
+ copy_socket_data(&dialog->socket, &peer->socket);
if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) &&
(!peer->maxms || ((peer->lastms >= 0) && (peer->lastms <= peer->maxms)))) {
@@ -4652,7 +4653,11 @@
}
ast_string_field_free_memory(p);
- return;
+
+ if (p->socket.ser) {
+ ao2_ref(p->socket.ser, -1);
+ p->socket.ser = NULL;
+ }
}
/*! \brief update_call_counter: Handle call_limit for SIP users
@@ -7946,11 +7951,7 @@
build_via(p);
ast_string_field_set(p, callid, callid);
- p->socket.lock = req->socket.lock;
- p->socket.type = req->socket.type;
- p->socket.fd = req->socket.fd;
- p->socket.port = req->socket.port;
- p->socket.ser = req->socket.ser;
+ copy_socket_data(&p->socket, &req->socket);
/* Use this temporary pvt structure to send the message */
__transmit_response(p, msg, req, XMIT_UNRELIABLE);
@@ -10317,7 +10318,8 @@
}
}
- pvt->socket = peer->socket = req->socket;
+ copy_socket_data(&peer->socket, &req->socket);
+ copy_socket_data(&pvt->socket, &peer->socket);
/* Look for brackets */
curi = contact;
@@ -19436,7 +19438,6 @@
req.socket.type = SIP_TRANSPORT_UDP;
req.socket.ser = NULL;
req.socket.port = bindaddr.sin_port;
- req.socket.lock = NULL;
handle_request_do(&req, &sin);
if (req.data) {
@@ -19491,7 +19492,7 @@
return 1;
}
- p->socket = req->socket;
+ copy_socket_data(&p->socket, &req->socket);
/* Go ahead and lock the owner if it has one -- we may need it */
/* becaues this is deadlock-prone, we need to try and unlock if failed */
@@ -19589,13 +19590,18 @@
if ((ser = sip_tcp_locate(&ca.sin))) {
s->fd = ser->fd;
+ if (s->ser) {
+ ao2_ref(s->ser, -1);
+ s->ser = NULL;
+ }
+ ao2_ref(ser, +1);
s->ser = ser;
return s->fd;
}
- if (s->ser && s->ser->parent->tls_cfg)
+ if (s->ser && s->ser->parent->tls_cfg) {
ca.tls_cfg = s->ser->parent->tls_cfg;
- else {
+ } else {
if (s->type & SIP_TRANSPORT_TLS) {
ca.tls_cfg = ast_calloc(1, sizeof(*ca.tls_cfg));
if (!ca.tls_cfg)
@@ -19605,7 +19611,12 @@
ast_copy_string(ca.hostname, p->tohost, sizeof(ca.hostname));
}
}
- s->ser = (!s->ser) ? ast_tcptls_client_start(&ca) : s->ser;
+
+ if (s->ser) {
+ /* the pvt socket already has a server instance ... */
+ } else {
+ s->ser = ast_tcptls_client_start(&ca);
+ }
if (!s->ser) {
if (ca.tls_cfg)
@@ -19615,8 +19626,12 @@
s->fd = ca.accept_fd;
- if (ast_pthread_create_background(&ca.master, NULL, sip_tcp_helper_thread, p)) {
+ /* Give the new thread a reference */
+ ao2_ref(s->ser, +1);
+
+ if (ast_pthread_create_background(&ca.master, NULL, sip_tcp_worker_fn, s->ser)) {
ast_debug(1, "Unable to launch '%s'.", ca.name);
+ ao2_ref(s->ser, -1);
close(ca.accept_fd);
s->fd = ca.accept_fd = -1;
}
Modified: trunk/include/asterisk/tcptls.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/tcptls.h?view=diff&rev=123546&r1=123545&r2=123546
==============================================================================
--- trunk/include/asterisk/tcptls.h (original)
+++ trunk/include/asterisk/tcptls.h Tue Jun 17 16:46:57 2008
@@ -50,6 +50,7 @@
#define _ASTERISK_SERVER_H
#include "asterisk/utils.h"
+#include "asterisk/astobj2.h"
#if defined(HAVE_OPENSSL) && (defined(HAVE_FUNOPEN) || defined(HAVE_FOPENCOOKIE))
#define DO_SSL /* comment in/out if you want to support ssl */
@@ -127,6 +128,7 @@
int client;
struct sockaddr_in requestor;
struct server_args *parent;
+ ast_mutex_t lock;
};
/*! \brief
@@ -166,11 +168,4 @@
HOOK_T ast_tcptls_server_read(struct ast_tcptls_session_instance *ser, void *buf, size_t count);
HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *ser, void *buf, size_t count);
-/*!
- * \brief Destroy a server instance
- *
- * \return NULL for convenience
- */
-struct ast_tcptls_session_instance *ast_tcptls_session_instance_destroy(struct ast_tcptls_session_instance *i);
-
#endif /* _ASTERISK_SERVER_H */
Modified: trunk/main/astobj2.c
URL: http://svn.digium.com/view/asterisk/trunk/main/astobj2.c?view=diff&rev=123546&r1=123545&r2=123546
==============================================================================
--- trunk/main/astobj2.c (original)
+++ trunk/main/astobj2.c Tue Jun 17 16:46:57 2008
@@ -930,12 +930,6 @@
ast_cli(a->fd, "object %d allocated as %p\n", i, obj);
sprintf(obj, "-- this is obj %d --", i);
ao2_link(c1, obj);
- /* At this point, the refcount on obj is 2 due to the allocation
- * and linking. We can go ahead and reduce the refcount by 1
- * right here so that when the container is unreffed later, the
- * objects will be freed
- */
- ao2_t_ref(obj, -1, "test");
}
ast_cli(a->fd, "testing callbacks\n");
ao2_t_callback(c1, 0, print_cb, &a->fd,"test callback");
Modified: trunk/main/http.c
URL: http://svn.digium.com/view/asterisk/trunk/main/http.c?view=diff&rev=123546&r1=123545&r2=123546
==============================================================================
--- trunk/main/http.c (original)
+++ trunk/main/http.c Tue Jun 17 16:46:57 2008
@@ -736,7 +736,8 @@
done:
fclose(ser->f);
- ser = ast_tcptls_session_instance_destroy(ser);
+ ao2_ref(ser, -1);
+ ser = NULL;
return NULL;
}
Modified: trunk/main/manager.c
URL: http://svn.digium.com/view/asterisk/trunk/main/manager.c?view=diff&rev=123546&r1=123545&r2=123546
==============================================================================
--- trunk/main/manager.c (original)
+++ trunk/main/manager.c Tue Jun 17 16:46:57 2008
@@ -3089,7 +3089,8 @@
destroy_session(s);
done:
- ser = ast_tcptls_session_instance_destroy(ser);
+ ao2_ref(ser, -1);
+ ser = NULL;
return NULL;
}
Modified: trunk/main/tcptls.c
URL: http://svn.digium.com/view/asterisk/trunk/main/tcptls.c?view=diff&rev=123546&r1=123545&r2=123546
==============================================================================
--- trunk/main/tcptls.c (original)
+++ trunk/main/tcptls.c Tue Jun 17 16:46:57 2008
@@ -83,6 +83,12 @@
HOOK_T ast_tcptls_server_read(struct ast_tcptls_session_instance *ser, void *buf, size_t count)
{
+ if (ser->fd == -1) {
+ ast_log(LOG_ERROR, "server_read called with an fd of -1\n");
+ errno = EIO;
+ return -1;
+ }
+
#ifdef DO_SSL
if (ser->ssl)
return ssl_read(ser->ssl, buf, count);
@@ -92,11 +98,23 @@
HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *ser, void *buf, size_t count)
{
+ if (ser->fd == -1) {
+ ast_log(LOG_ERROR, "server_write called with an fd of -1\n");
+ errno = EIO;
+ return -1;
+ }
+
#ifdef DO_SSL
if (ser->ssl)
return ssl_write(ser->ssl, buf, count);
#endif
return write(ser->fd, buf, count);
+}
+
+static void session_instance_destructor(void *obj)
+{
+ struct ast_tcptls_session_instance *i = obj;
+ ast_mutex_destroy(&i->lock);
}
void *ast_tcptls_server_root(void *data)
@@ -123,12 +141,15 @@
ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
continue;
}
- ser = ast_calloc(1, sizeof(*ser));
+ ser = ao2_alloc(sizeof(*ser), session_instance_destructor);
if (!ser) {
ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
close(fd);
continue;
}
+
+ ast_mutex_init(&ser->lock);
+
flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
ser->fd = fd;
@@ -140,7 +161,7 @@
if (ast_pthread_create_detached_background(&launched, NULL, ast_make_file_from_fd, ser)) {
ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
close(ser->fd);
- ast_free(ser);
+ ao2_ref(ser, -1);
}
}
return NULL;
@@ -235,8 +256,10 @@
goto error;
}
- if (!(ser = ast_calloc(1, sizeof(*ser))))
- goto error;
+ if (!(ser = ao2_alloc(sizeof(*ser), session_instance_destructor)))
+ goto error;
+
+ ast_mutex_init(&ser->lock);
flags = fcntl(desc->accept_fd, F_GETFL);
fcntl(desc->accept_fd, F_SETFL, flags & ~O_NONBLOCK);
@@ -262,7 +285,7 @@
close(desc->accept_fd);
desc->accept_fd = -1;
if (ser)
- ast_free(ser);
+ ao2_ref(ser, -1);
return NULL;
}
@@ -447,8 +470,3 @@
return ser;
}
-struct ast_tcptls_session_instance *ast_tcptls_session_instance_destroy(struct ast_tcptls_session_instance *i)
-{
- ast_free(i);
- return NULL;
-}
More information about the asterisk-commits
mailing list