This is an automated email from the ASF dual-hosted git repository.

cliffjansen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git

commit 0987726b3dd34da77bf826ac3cfb5b6fc19ba60b
Author: Clifford Jansen <cliffjan...@apache.org>
AuthorDate: Wed Sep 13 19:06:04 2023 -0700

    PROTON-2763: Raw connection double DISCONNECT event
---
 c/src/proactor/epoll_raw_connection.c    | 16 ++++++++++++----
 c/src/proactor/raw_connection-internal.h |  1 +
 c/src/proactor/raw_connection.c          |  7 ++++++-
 3 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/c/src/proactor/epoll_raw_connection.c 
b/c/src/proactor/epoll_raw_connection.c
index c0e731066..83f950b02 100644
--- a/c/src/proactor/epoll_raw_connection.c
+++ b/c/src/proactor/epoll_raw_connection.c
@@ -382,6 +382,12 @@ pn_event_batch_t *pni_raw_connection_process(task_t *t, 
uint32_t io_events, bool
     else
       pni_task_wake_done(&rc->task);  // Complete task wake without event.
   }
+  if (pni_raw_finished(&rc->raw_connection)) {
+    unlock(&rc->task.mutex);
+    pni_raw_finalize(&rc->raw_connection);
+    praw_connection_cleanup(rc);
+    return NULL;
+  }
   int events = io_events;
   int fd = rc->psocket.epoll_io.fd;
   if (!rc->connected) {
@@ -445,18 +451,18 @@ void pni_raw_connection_done(praw_connection_t *rc) {
   bool have_event = pni_raw_batch_has_events(raw);
 
   lock(&rc->task.mutex);
+  bool wake_pending = pni_task_wake_pending(&rc->task) && 
pni_raw_can_wake(raw);
   pn_proactor_t *p = rc->task.proactor;
   tslot_t *ts = rc->task.runner;
   rc->task.working = false;
   // The task may be in the ready state even if we've got no raw connection
   // wakes outstanding because we dealt with it already in pni_raw_batch_next()
-  notify = (pni_task_wake_pending(&rc->task) || have_event) && 
schedule(&rc->task);
+  notify = (wake_pending || have_event) && schedule(&rc->task);
   ready = rc->task.ready;  // No need to poll.  Already scheduled.
   unlock(&rc->task.mutex);
 
-  bool finished_disconnect = raw->state==conn_fini && !ready && 
!raw->disconnectpending;
-  if (finished_disconnect) {
-    // If we're closed and we've sent the disconnect then close
+  if (pni_raw_finished(raw) && !ready) {
+    // If raw connection has no more work to do and safe to free resources, do 
so.
     pni_raw_finalize(raw);
     praw_connection_cleanup(rc);
   } else if (ready) {
@@ -479,6 +485,8 @@ void pni_raw_connection_done(praw_connection_t *rc) {
     }
   }
 
+  // praw_connection_cleanup() may have been called above. Can no longer touch 
rc or raw.
+
   lock(&p->sched_mutex);
   tslot_t *resume_thread;
   notify |= unassign_thread(p, ts, UNUSED, &resume_thread);
diff --git a/c/src/proactor/raw_connection-internal.h 
b/c/src/proactor/raw_connection-internal.h
index cdfd5a852..fe0e29fe0 100644
--- a/c/src/proactor/raw_connection-internal.h
+++ b/c/src/proactor/raw_connection-internal.h
@@ -141,6 +141,7 @@ pn_event_t *pni_raw_event_next(pn_raw_connection_t *conn);
 bool pni_raw_batch_has_events(pn_raw_connection_t *conn);
 void pni_raw_initialize(pn_raw_connection_t *conn);
 void pni_raw_finalize(pn_raw_connection_t *conn);
+bool pni_raw_finished(pn_raw_connection_t *conn);
 
 #ifdef __cplusplus
 }
diff --git a/c/src/proactor/raw_connection.c b/c/src/proactor/raw_connection.c
index 89fbbd1dd..0c2118e01 100644
--- a/c/src/proactor/raw_connection.c
+++ b/c/src/proactor/raw_connection.c
@@ -484,10 +484,15 @@ bool pni_raw_wake_is_pending(pn_raw_connection_t *conn) {
 }
 
 bool pni_raw_can_wake(pn_raw_connection_t *conn) {
-  // True if DISCONNECTED event has not yet been extracted from the batch.
+  // True if DISCONNECTED event has not yet been generated.
   return (conn->disconnect_state != disc_fini);
 }
 
+bool pni_raw_finished(pn_raw_connection_t *conn) {
+  // True if state machine is in final state and application has consumed 
final DISCONNECTED event.
+  return (conn->disconnect_state == disc_fini && 
pn_collector_peek(conn->collector) == NULL);
+}
+
 void pni_raw_read(pn_raw_connection_t *conn, int sock, long (*recv)(int, 
void*, size_t), void(*set_error)(pn_raw_connection_t *, const char *, int)) {
   assert(conn);
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org
For additional commands, e-mail: commits-h...@qpid.apache.org

Reply via email to