<p>Joshua Colp <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/18720">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Kevin Harwell: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved
  Joshua Colp: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">websocket / aeap: Handle poll() interruptions better.<br><br>A sporadic test failure was happening when executing the AEAP<br>Websocket transport tests. It was originally thought this was<br>due to things not getting cleaned up fast enough, but upon further<br>investigation I determined the underlying cause was poll()<br>getting interrupted and this not being handled in all places.<br><br>This change adds EINTR and EAGAIN handling to the Websocket<br>client connect code as well as the AEAP Websocket transport code.<br>If either occur then the code will just go back to waiting<br>for data.<br><br>The originally disabled failure test case has also been<br>re-enabled.<br><br>ASTERISK-30099<br><br>Change-Id: I1711a331ecf5d35cd542911dc6aaa9acf1e172ad<br>---<br>M res/res_aeap/transport_websocket.c<br>M res/res_http_websocket.c<br>M tests/test_aeap_transport.c<br>3 files changed, 28 insertions(+), 16 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/res/res_aeap/transport_websocket.c b/res/res_aeap/transport_websocket.c</span><br><span>index 5f1a406..801e4d8 100644</span><br><span>--- a/res/res_aeap/transport_websocket.c</span><br><span>+++ b/res/res_aeap/transport_websocket.c</span><br><span>@@ -103,7 +103,12 @@</span><br><span>        * unlock it prior to waiting.</span><br><span>        */</span><br><span>  ast_mutex_unlock(&transport->base.read_lock);</span><br><span style="color: hsl(0, 100%, 40%);">-    if (ast_websocket_wait_for_input(transport->ws, -1) <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+     while (ast_websocket_wait_for_input(transport->ws, -1) <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* If this was poll getting interrupted just go back to waiting */</span><br><span style="color: hsl(120, 100%, 40%);">+            if (errno == EINTR || errno == EAGAIN) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          ast_mutex_lock(&transport->base.read_lock);</span><br><span>           log_error(self, "poll failure: %s", strerror(errno));</span><br><span>              /* Ensure this transport is in a disconnected state */</span><br><span>diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c</span><br><span>index d0a5ea7..f8da487 100644</span><br><span>--- a/res/res_http_websocket.c</span><br><span>+++ b/res/res_http_websocket.c</span><br><span>@@ -1308,7 +1308,11 @@</span><br><span>         int has_accept = 0;</span><br><span>  int has_protocol = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       if (ast_iostream_gets(client->ser->stream, buf, sizeof(buf)) <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ while (ast_iostream_gets(client->ser->stream, buf, sizeof(buf)) <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (errno == EINTR || errno == EAGAIN) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          ast_log(LOG_ERROR, "Unable to retrieve HTTP status line.");</span><br><span>                return WS_BAD_STATUS;</span><br><span>        }</span><br><span>@@ -1321,10 +1325,19 @@</span><br><span> </span><br><span>      /* Ignoring line folding - assuming header field values are contained</span><br><span>           within a single line */</span><br><span style="color: hsl(0, 100%, 40%);">-      while (ast_iostream_gets(client->ser->stream, buf, sizeof(buf)) > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+       while (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ssize_t len = ast_iostream_gets(client->ser->stream, buf, sizeof(buf));</span><br><span>                char *name, *value;</span><br><span style="color: hsl(0, 100%, 40%);">-             int parsed = ast_http_header_parse(buf, &name, &value);</span><br><span style="color: hsl(120, 100%, 40%);">+               int parsed;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+               if (len <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (errno == EINTR || errno == EAGAIN) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           parsed = ast_http_header_parse(buf, &name, &value);</span><br><span>          if (parsed < 0) {</span><br><span>                         break;</span><br><span>               }</span><br><span>@@ -1360,6 +1373,7 @@</span><br><span>                    return WS_NOT_SUPPORTED;</span><br><span>             }</span><br><span>    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  return has_upgrade && has_connection && has_accept ?</span><br><span>                 WS_OK : WS_HEADER_MISSING;</span><br><span> }</span><br><span>diff --git a/tests/test_aeap_transport.c b/tests/test_aeap_transport.c</span><br><span>index e864d44..cee9c9e 100644</span><br><span>--- a/tests/test_aeap_transport.c</span><br><span>+++ b/tests/test_aeap_transport.c</span><br><span>@@ -134,22 +134,15 @@</span><br><span> </span><br><span>         ast_test_validate(test, !aeap_transport_is_connected(transport));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /*</span><br><span style="color: hsl(0, 100%, 40%);">-       * The following section of code has been disabled as it may be the cause</span><br><span style="color: hsl(0, 100%, 40%);">-        * of subsequent test failures.</span><br><span style="color: hsl(0, 100%, 40%);">-  *</span><br><span style="color: hsl(0, 100%, 40%);">-       * See ASTERISK-30099 for more information</span><br><span style="color: hsl(0, 100%, 40%);">-       */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     /* aeap_transport_destroy(transport); */</span><br><span style="color: hsl(120, 100%, 40%);">+      aeap_transport_destroy(transport);</span><br><span> </span><br><span>       /* /\* Test invalid protocol *\/ */</span><br><span style="color: hsl(0, 100%, 40%);">-     /* ast_test_validate(test, (transport = aeap_transport_create(TRANSPORT_URL))); */</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_test_validate(test, (transport = aeap_transport_create(TRANSPORT_URL)));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        /* ast_test_validate(test, aeap_transport_connect(transport, */</span><br><span style="color: hsl(0, 100%, 40%);">- /*      TRANSPORT_URL, TRANSPORT_PROTOCOL_INVALID, TRANSPORT_TIMEOUT)); */</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_test_validate(test, aeap_transport_connect(transport,</span><br><span style="color: hsl(120, 100%, 40%);">+             TRANSPORT_URL, TRANSPORT_PROTOCOL_INVALID, TRANSPORT_TIMEOUT));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     /* ast_test_validate(test, !aeap_transport_is_connected(transport)); */</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_test_validate(test, !aeap_transport_is_connected(transport));</span><br><span> </span><br><span>        return AST_TEST_PASS;</span><br><span> }</span><br><span></span><br></pre><div style="white-space:pre-wrap"></div><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/18720">change 18720</a>. To unsubscribe, or for help writing mail filters, 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/c/asterisk/+/18720"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I1711a331ecf5d35cd542911dc6aaa9acf1e172ad </div>
<div style="display:none"> Gerrit-Change-Number: 18720 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>