<p>Richard Mudgett has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/9217">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">channel.c: Fix usage of CHECK_BLOCKING()<br><br>The CHECK_BLOCKING() macro is used to indicate if a channel's handling<br>thread is about to do a blocking operation (poll, read, or write) of<br>media. A few operations such as ast_queue_frame(), soft hangup, and<br>masquerades use the indication to wake up the blocked thread to reevaluate<br>what is going on.<br><br>ASTERISK-27625<br><br>Change-Id: I4dfc33e01e60627d962efa29d0a4244cf151a84d<br>---<br>M include/asterisk/channel.h<br>M main/channel.c<br>2 files changed, 44 insertions(+), 23 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/17/9217/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h<br>index 16b8a7b..d0c0dbf 100644<br>--- a/include/asterisk/channel.h<br>+++ b/include/asterisk/channel.h<br>@@ -2758,15 +2758,30 @@<br> return state;<br> }<br> <br>-#define CHECK_BLOCKING(c) do { \<br>- if (ast_test_flag(ast_channel_flags(c), AST_FLAG_BLOCKING)) {\<br>- ast_debug(1, "Thread %p is blocking '%s', already blocked by thread %p in procedure %s\n", \<br>- (void *) pthread_self(), ast_channel_name(c), (void *) ast_channel_blocker(c), ast_channel_blockproc(c)); \<br>- } else { \<br>+/*!<br>+ * \brief Set the blocking indication on the channel.<br>+ *<br>+ * \details<br>+ * Indicate that the thread handling the channel is about to do a blocking<br>+ * operation to wait for media on the channel. (poll, read, or write)<br>+ *<br>+ * Masquerading and ast_queue_frame() use this indication to wake up the thread.<br>+ *<br>+ * \pre The channel needs to be locked<br>+ */<br>+#define CHECK_BLOCKING(c) \<br>+ do { \<br>+ if (ast_test_flag(ast_channel_flags(c), AST_FLAG_BLOCKING)) { \<br>+ /* This should not happen as there should only be one thread handling a channel's media at a time. */ \<br>+ ast_log(LOG_DEBUG, "Thread %p is blocking '%s', already blocked by thread %p in procedure %s\n", \<br>+ (void *) pthread_self(), ast_channel_name(c), \<br>+ (void *) ast_channel_blocker(c), ast_channel_blockproc(c)); \<br>+ ast_assert(0); \<br>+ } \<br> ast_channel_blocker_set((c), pthread_self()); \<br> ast_channel_blockproc_set((c), __PRETTY_FUNCTION__); \<br> ast_set_flag(ast_channel_flags(c), AST_FLAG_BLOCKING); \<br>- } } while (0)<br>+ } while (0)<br> <br> ast_group_t ast_get_group(const char *s);<br> <br>diff --git a/main/channel.c b/main/channel.c<br>index a29c968..6386de2 100644<br>--- a/main/channel.c<br>+++ b/main/channel.c<br>@@ -5055,11 +5055,9 @@<br> /* There is a generator running while we're in the middle of a digit.<br> * It's probably inband DTMF, so go ahead and pass it so it can<br> * stop the generator */<br>- ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);<br> ast_channel_unlock(chan);<br> res = ast_senddigit_end(chan, fr->subclass.integer, fr->len);<br> ast_channel_lock(chan);<br>- CHECK_BLOCKING(chan);<br> } else if (fr->frametype == AST_FRAME_CONTROL<br> && fr->subclass.integer == AST_CONTROL_UNHOLD) {<br> /*<br>@@ -5077,7 +5075,6 @@<br> /* High bit prints debugging */<br> if (ast_channel_fout(chan) & DEBUGCHAN_FLAG)<br> ast_frame_dump(ast_channel_name(chan), fr, ">>");<br>- CHECK_BLOCKING(chan);<br> switch (fr->frametype) {<br> case AST_FRAME_CONTROL:<br> indicate_data_internal(chan, fr->subclass.integer, fr->data.ptr, fr->datalen);<br>@@ -5091,11 +5088,9 @@<br> f = fr;<br> }<br> send_dtmf_begin_event(chan, DTMF_SENT, fr->subclass.integer);<br>- ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);<br> ast_channel_unlock(chan);<br> res = ast_senddigit_begin(chan, fr->subclass.integer);<br> ast_channel_lock(chan);<br>- CHECK_BLOCKING(chan);<br> break;<br> case AST_FRAME_DTMF_END:<br> if (ast_channel_audiohooks(chan)) {<br>@@ -5107,13 +5102,12 @@<br> }<br> }<br> send_dtmf_end_event(chan, DTMF_SENT, fr->subclass.integer, fr->len);<br>- ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);<br> ast_channel_unlock(chan);<br> res = ast_senddigit_end(chan, fr->subclass.integer, fr->len);<br> ast_channel_lock(chan);<br>- CHECK_BLOCKING(chan);<br> break;<br> case AST_FRAME_TEXT:<br>+ CHECK_BLOCKING(chan);<br> if (ast_format_cmp(fr->subclass.format, ast_format_t140) == AST_FORMAT_CMP_EQUAL) {<br> res = (ast_channel_tech(chan)->write_text == NULL) ? 0 :<br> ast_channel_tech(chan)->write_text(chan, fr);<br>@@ -5121,13 +5115,17 @@<br> res = (ast_channel_tech(chan)->send_text == NULL) ? 0 :<br> ast_channel_tech(chan)->send_text(chan, (char *) fr->data.ptr);<br> }<br>+ ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);<br> break;<br> case AST_FRAME_HTML:<br>+ CHECK_BLOCKING(chan);<br> res = (ast_channel_tech(chan)->send_html == NULL) ? 0 :<br> ast_channel_tech(chan)->send_html(chan, fr->subclass.integer, (char *) fr->data.ptr, fr->datalen);<br>+ ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);<br> break;<br> case AST_FRAME_VIDEO:<br> /* XXX Handle translation of video codecs one day XXX */<br>+ CHECK_BLOCKING(chan);<br> if (ast_channel_tech(chan)->write_stream) {<br> if (stream) {<br> res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr);<br>@@ -5139,8 +5137,10 @@<br> } else {<br> res = 0;<br> }<br>+ ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);<br> break;<br> case AST_FRAME_MODEM:<br>+ CHECK_BLOCKING(chan);<br> if (ast_channel_tech(chan)->write_stream) {<br> if (stream) {<br> res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr);<br>@@ -5152,6 +5152,7 @@<br> } else {<br> res = 0;<br> }<br>+ ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);<br> break;<br> case AST_FRAME_VOICE:<br> if (ast_opt_generic_plc && ast_format_cmp(fr->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {<br>@@ -5201,15 +5202,15 @@<br> <br> if (ast_channel_writetrans(chan)) {<br> struct ast_frame *trans_frame = ast_translate(ast_channel_writetrans(chan), f, 0);<br>- if (trans_frame != f && f != fr) {<br>- /*<br>- * If translate gives us a new frame and so did the audio<br>- * hook then we need to free the one from the audio hook.<br>- */<br>- ast_frfree(f);<br>- }<br>- f = trans_frame;<br>- }<br>+ if (trans_frame != f && f != fr) {<br>+ /*<br>+ * If translate gives us a new frame and so did the audio<br>+ * hook then we need to free the one from the audio hook.<br>+ */<br>+ ast_frfree(f);<br>+ }<br>+ f = trans_frame;<br>+ }<br> }<br> <br> if (!f) {<br>@@ -5307,6 +5308,7 @@<br> /* the translator on chan->writetrans may have returned multiple frames<br> from the single frame we passed in; if so, feed each one of them to the<br> channel, freeing each one after it has been written */<br>+ CHECK_BLOCKING(chan);<br> if ((f != fr) && AST_LIST_NEXT(f, frame_list)) {<br> struct ast_frame *cur, *next = NULL;<br> unsigned int skip = 0;<br>@@ -5345,6 +5347,7 @@<br> res = 0;<br> }<br> }<br>+ ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);<br> break;<br> case AST_FRAME_NULL:<br> case AST_FRAME_IAX:<br>@@ -5353,23 +5356,26 @@<br> break;<br> case AST_FRAME_RTCP:<br> /* RTCP information is on a per-stream basis and only available on multistream capable channels */<br>+ CHECK_BLOCKING(chan);<br> if (ast_channel_tech(chan)->write_stream && stream) {<br> res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr);<br> } else {<br> res = 0;<br> }<br>+ ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);<br> break;<br> default:<br> /* At this point, fr is the incoming frame and f is NULL. Channels do<br> * not expect to get NULL as a frame pointer and will segfault. Hence,<br> * we output the original frame passed in. */<br>+ CHECK_BLOCKING(chan);<br> res = ast_channel_tech(chan)->write(chan, fr);<br>+ ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);<br> break;<br> }<br> <br> if (f && f != fr)<br> ast_frfree(f);<br>- ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);<br> <br> /* Consider a write failure to force a soft hangup */<br> if (res < 0) {<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/9217">change 9217</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/9217"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 15 </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I4dfc33e01e60627d962efa29d0a4244cf151a84d </div>
<div style="display:none"> Gerrit-Change-Number: 9217 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Richard Mudgett <rmudgett@digium.com> </div>