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