This is an automated email from the ASF dual-hosted git repository. kgiusti pushed a commit to branch 1.17.x in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git
commit fd44505ca630e30ddca055723b2c80dd6ff8b065 Author: Ganesh Murthy <gmur...@apache.org> AuthorDate: Wed Oct 27 12:07:11 2021 -0400 DISPATCH-2264: Fix for router crash when deleting listener --- src/adaptors/http2/http2_adaptor.c | 37 +++++++++++++++++--------- tests/system_tests_http2.py | 54 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 14 deletions(-) diff --git a/src/adaptors/http2/http2_adaptor.c b/src/adaptors/http2/http2_adaptor.c index 19ed791..0ff8e10 100644 --- a/src/adaptors/http2/http2_adaptor.c +++ b/src/adaptors/http2/http2_adaptor.c @@ -2648,9 +2648,25 @@ static void handle_listener_event(pn_event_t *e, qd_server_t *qd_server, void *c } break; - case PN_LISTENER_CLOSE: - qd_log(log, QD_LOG_INFO, "Closing HTTP connection on %s", host_port); - break; + case PN_LISTENER_CLOSE: { + if (li->pn_listener) { + pn_condition_t *cond = pn_listener_condition(li->pn_listener); + if (pn_condition_is_set(cond)) { + qd_log(log, QD_LOG_ERROR, "Listener error on %s: %s (%s)", host_port, pn_condition_get_description(cond), pn_condition_get_name(cond)); + } + else { + qd_log(log, QD_LOG_TRACE, "Listener closed on %s", host_port); + } + } + + sys_mutex_lock(http2_adaptor->lock); + pn_listener_set_context(li->pn_listener, 0); + li->pn_listener = 0; + DEQ_REMOVE(http2_adaptor->listeners, li); + sys_mutex_unlock(http2_adaptor->lock); + qd_http_listener_decref(li); + } + break; default: break; @@ -2682,18 +2698,13 @@ void qd_http2_delete_connector(qd_dispatch_t *qd, qd_http_connector_t *connector */ void qd_http2_delete_listener(qd_dispatch_t *qd, qd_http_listener_t *li) { + sys_mutex_lock(http2_adaptor->lock); if (li) { if (li->pn_listener) { pn_listener_close(li->pn_listener); - li->pn_listener = 0; } - sys_mutex_lock(http2_adaptor->lock); - DEQ_REMOVE(http2_adaptor->listeners, li); - sys_mutex_unlock(http2_adaptor->lock); - - qd_log(http2_adaptor->log_source, QD_LOG_INFO, "Deleted HttpListener for %s, %s:%s", li->config.address, li->config.host, li->config.port); - qd_http_listener_decref(li); } + sys_mutex_unlock(http2_adaptor->lock); } @@ -2750,14 +2761,16 @@ static void qdr_http2_adaptor_final(void *adaptor_context) // Free all http listeners qd_http_listener_t *li = DEQ_HEAD(adaptor->listeners); while (li) { - qd_http2_delete_listener(0, li); + DEQ_REMOVE_HEAD(adaptor->listeners); + qd_http_listener_decref(li); li = DEQ_HEAD(adaptor->listeners); } // Free all http connectors qd_http_connector_t *ct = DEQ_HEAD(adaptor->connectors); while (ct) { - qd_http2_delete_connector(0, ct); + DEQ_REMOVE_HEAD(adaptor->connectors); + qd_http_connector_decref(ct); ct = DEQ_HEAD(adaptor->connectors); } diff --git a/tests/system_tests_http2.py b/tests/system_tests_http2.py index 7d09f6f..e09c494 100644 --- a/tests/system_tests_http2.py +++ b/tests/system_tests_http2.py @@ -218,6 +218,43 @@ class CommonHttp2Tests: digest_of_response_file = get_digest(self.router_qdra.outdir + image_file_name) self.assertEqual(digest_of_server_file, digest_of_response_file) + def check_listener_delete(self, client_addr, server_addr): + # Run curl 127.0.0.1:port --http2-prior-knowledge + # We are first making sure that the http request goes thru successfully. + out = self.run_curl(client_addr) + ret_string = "" + i = 0 + while (i < 1000): + ret_string += str(i) + "," + i += 1 + self.assertIn(ret_string, out) + + qd_manager = QdManager(self, address=server_addr) + http_listeners = qd_manager.query('org.apache.qpid.dispatch.httpListener') + self.assertEqual(len(http_listeners), 1) + + # Run a qdmanage DELETE on the httpListener + qd_manager.delete("org.apache.qpid.dispatch.httpListener", name=self.listener_name) + + # Make sure the listener is gone + http_listeners = qd_manager.query('org.apache.qpid.dispatch.httpListener') + self.assertEqual(len(http_listeners), 0) + + # Try running a curl command against the listener to make sure it times out + request_timed_out = False + try: + out = self.run_curl(client_addr, timeout=3) + except Exception as e: + request_timed_out = True + self.assertTrue(request_timed_out) + + # Add back the listener and run a curl command to make sure that the newly added listener is + # back up and running. + create_result = qd_manager.create("org.apache.qpid.dispatch.httpListener", self.http_listener_props) + sleep(2) + out = self.run_curl(client_addr) + self.assertIn(ret_string, out) + def check_connector_delete(self, client_addr, server_addr): # Run curl 127.0.0.1:port --http2-prior-knowledge # We are first making sure that the http request goes thru successfully. @@ -468,12 +505,20 @@ class Http2TestTwoRouter(Http2TestBase, CommonHttp2Tests): server_file="http2_server.py") name = "http2-test-router" inter_router_port = cls.tester.get_port() + cls.http_listener_port = cls.tester.get_port() + cls.listener_name = 'listenerToBeDeleted' + cls.http_listener_props = { + 'port': cls.http_listener_port, + 'address': 'examples', + 'host': '127.0.0.1', + 'protocolVersion': 'HTTP2', + 'name': cls.listener_name + } config_qdra = Qdrouterd.Config([ ('router', {'mode': 'interior', 'id': 'QDR.A'}), ('listener', {'port': cls.tester.get_port(), 'role': 'normal', 'host': '0.0.0.0'}), - ('httpListener', {'port': cls.tester.get_port(), 'address': 'examples', - 'host': '127.0.0.1', 'protocolVersion': 'HTTP2'}), + ('httpListener', cls.http_listener_props), ('listener', {'role': 'inter-router', 'port': inter_router_port}) ]) @@ -553,6 +598,11 @@ class Http2TestTwoRouter(Http2TestBase, CommonHttp2Tests): self.assertEqual(stats_b[0].get('bytesIn'), 3944) @unittest.skipIf(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests") + def test_yyy_http_listener_delete(self): + self.check_listener_delete(client_addr=self.router_qdra.http_addresses[0], + server_addr=self.router_qdra.addresses[0]) + + @unittest.skipIf(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests") def test_zzz_http_connector_delete(self): self.check_connector_delete(client_addr=self.router_qdra.http_addresses[0], server_addr=self.router_qdrb.addresses[0]) --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org