Re: mISDN_send: error -12 strikes again

Ralf Schlatterbeck <[email protected]>
Newsgroups gmane.linux.isdn.i4l.user
Message-ID <[email protected]>
Yet another Scenario of a deadlock:

thread               name       lock       file        function              line
0xb6157b70           c          0x975a640  astobj2.c   internal_ao2_callback  657
0xb6157b70           chan       0xfd1e9f8  channel.c   ast_channel_cmp_cb    1691

Waiting for:                               channel.c   ast_indicate_data     4323


0xb4beeb70           chan       0xfd1e9f8  channel.c   ast_indicate_data     4323
0xb4beeb70           &chan_lock 0xb5c55a80 chan_lcr.c  lcr_indicate          2920

Waiting for:                               chan_lcr.c  lock_chan             2012

Information for chan_lcr.c  lock_chan is missing.

but it is this one:

Thread 19 (Thread 0xb56bfb70 (LWP 2343)):
#0  0xb7814424 in __kernel_vsyscall ()
#1  0xb7526c89 in __lll_lock_wait () from /lib/i686/cmov/libpthread.so.0
#2  0xb7522099 in _L_lock_839 () from /lib/i686/cmov/libpthread.so.0
#3  0xb7521f2b in pthread_mutex_lock () from /lib/i686/cmov/libpthread.so.0
#4  0x08113001 in __ast_pthread_mutex_lock (filename=0x81b8fbc "astobj2.c", 
    lineno=493, func=0x81b91bd "internal_ao2_link", mutex_name=0x81b90b8 "c", 
    t=0x975a640) at lock.c:244
#5  0x080851f8 in __ao2_lock (user_data=0x975a670, file=0x81b8fbc "astobj2.c", 
    func=0x81b91bd "internal_ao2_link", line=493, var=0x81b90b8 "c")
    at astobj2.c:157
#6  0x080858f9 in internal_ao2_link (c=0x975a670, user_data=0xfd85498, 
    file=0x81b8fbc "astobj2.c", line=517, func=0x81b91a1 "__ao2_link")
    at astobj2.c:493
#7  0x08085a7a in __ao2_link (c=0x975a670, user_data=0xfd85498)
    at astobj2.c:517
#8  0x080a803f in __ast_channel_alloc_ap (needqueue=1, state=1, cid_num=0x0, 
    cid_name=0x0, acctcode=0xb5c5152b "", exten=0x0, context=0xb5c5152b "", 
    linkedid=0xb5c5152b "", amaflag=0, file=0xb5c5121f "chan_lcr.c", line=924, 
    function=0xb5c53dde "lcr_in_setup", name_fmt=0xb5c514f3 "%s/%d", 
    ap1=0xb56a63f4 "\fT\305\265\020\001", ap2=0xb56a63f4 "\fT\305\265\020\001")
    at channel.c:1312
#9  0x080a82a8 in __ast_channel_alloc (needqueue=1, state=1, cid_num=0x0, 
    cid_name=0x0, acctcode=0xb5c5152b "", exten=0x0, context=0xb5c5152b "", 
    linkedid=0xb5c5152b "", amaflag=0, file=0xb5c5121f "chan_lcr.c", line=924, 
    function=0xb5c53dde "lcr_in_setup", name_fmt=0xb5c514f3 "%s/%d")
    at channel.c:1357
#10 0xb5c4c93e in lcr_in_setup (fd=0xb5c55a60, what=<value optimized out>, 
    instance=0x0, index=0) at chan_lcr.c:924
#11 receive_message (fd=0xb5c55a60, what=<value optimized out>, instance=0x0, 
    index=0) at chan_lcr.c:1666
#12 handle_socket (fd=0xb5c55a60, what=<value optimized out>, instance=0x0, 
    index=0) at chan_lcr.c:1801
#13 0xb5c50d5c in select_main (polling=0, global_change=0xb5c558c8, 
    lock=0xb5c45a80 <lock_chan>, unlock=0xb5c45ad0 <unlock_chan>)
    at select.c:168

Offending call: ast_channel_alloc

I've tried to patch this as attached but when running my stress-test,
asterisk gets into a state where it no longer accepts calls (lcradmin
state doesn't show *any* call activity) -- silently, the call just
hangs. But we don't get any deadlocks anymore. Looks like somehow data
structures get inconsistent somewhere.

I've also tried to *always* lock in lcr_hangup (not conditionally by
thread id, I think this is a bad idea) but this doesn't change anything,
the change is also in the patch below.

But this is still the version where hfcmulti isn't working (one-way
audio, see separate emails), so this might be related to the hfcmulti
bug, I will have to test this on an older version of the mISDN stack to
confirm.

The "good" news is that I'm down to below a minute when trying to
reproduce this by running 4 processes that start calls and one process
that tears down calls simulateneously. With this setup I'm able to
reliably get the deadlock in under a minute. The state described above
where Asterisk no longer accepts calls is reached after several minutes.

Patch, do not apply, just for illustration:

diff --git a/chan_lcr.c b/chan_lcr.c
index df5b4fc..2fc705e 100644
--- a/chan_lcr.c
+++ b/chan_lcr.c
@@ -913,7 +913,10 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
 
 	CDEBUG(call, NULL, "Incomming setup from LCR. (callerid %s, dialing %s)\n", param->setup.callerinfo.id, param->setup.dialinginfo.id);
 
-	/* create asterisk channel instrance */
+        /* Unlock before calling into asterisk! */
+        ast_mutex_unlock(&chan_lock);
+        
+	/* create asterisk channel instance */
 
 	#ifdef LCR_FOR_CALLWEAVER
 	ast = ast_channel_alloc(1);
@@ -927,6 +930,9 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
 #endif
 	#endif
 
+        /* Re-lock after calling into asterisk! */
+        ast_mutex_lock(&chan_lock);
+
 	if (!ast) {
 		/* release */
 		CERROR(call, NULL, "Failed to create Asterisk channel - releasing.\n");
@@ -1498,7 +1504,7 @@ void lcr_in_dtmf(struct chan_call *call, int val)
 /*
  * message received from LCR
  */
-int receive_message(int message_type, unsigned int ref, union parameter *param)
+static int receive_message(int message_type, unsigned int ref, union parameter *param)
 {
 	struct bchannel *bchannel;
 	struct chan_call *call;
@@ -2082,7 +2088,10 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c
 		return NULL;
 	}
 
-	/* create asterisk channel instrance */
+        /* Unlock before calling into asterisk! */
+        ast_mutex_unlock(&chan_lock);
+        
+	/* create asterisk channel instance */
 
 	#ifdef LCR_FOR_ASTERISK
 #ifdef AST_1_8_OR_HIGHER
@@ -2096,6 +2105,9 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c
 	ast = ast_channel_alloc(1);
 	#endif
 
+        /* Re-lock after calling into asterisk! */
+        ast_mutex_lock(&chan_lock);
+
 	if (!ast) {
 		CERROR(NULL, NULL, "Failed to create Asterisk channel.\n");
 		free_call(call);
@@ -2678,9 +2690,7 @@ static int lcr_hangup(struct ast_channel *ast)
 	struct chan_call *call;
 	pthread_t tid = pthread_self();
 
-	if (!pthread_equal(tid, chan_tid)) {
-		ast_mutex_lock(&chan_lock);
-	}
+	ast_mutex_lock(&chan_lock);
 #if ASTERISK_VERSION_NUM < 110000
 	call = ast->tech_pvt;
 #else
@@ -2688,9 +2698,7 @@ static int lcr_hangup(struct ast_channel *ast)
 #endif
 	if (!call) {
 		CERROR(NULL, ast, "Received hangup from Asterisk, but no call instance exists.\n");
-		if (!pthread_equal(tid, chan_tid)) {
-			ast_mutex_unlock(&chan_lock);
-		}
+		ast_mutex_unlock(&chan_lock);
 		return -1;
 	}
 
@@ -2720,9 +2728,7 @@ static int lcr_hangup(struct ast_channel *ast)
 			send_release_and_import(call, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL);
 		/* remove call */
 		free_call(call);
-		if (!pthread_equal(tid, chan_tid)) {
-			ast_mutex_unlock(&chan_lock);
-		}
+		ast_mutex_unlock(&chan_lock);
 		return 0;
 	} else {
 		/* ref is not set, due to prepare setup or release */
@@ -2737,9 +2743,7 @@ static int lcr_hangup(struct ast_channel *ast)
 			call->ast = NULL;
 		}
 	}
-	if (!pthread_equal(tid, chan_tid)) {
-		ast_mutex_unlock(&chan_lock);
-	}
+	ast_mutex_unlock(&chan_lock);
 	return 0;
 }
 

-- 
Ralf Schlatterbeck             email: [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.