From bdd90aeb65d82ecae8fe58b441d25a1e1b129bf3 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Sat, 29 Jan 2022 02:15:10 +1300 Subject: [PATCH 1/3] Add low level socket events for libpq. Provide a way to get a callback when a socket is created or closed. XXX TODO handle callback failure XXX TODO investigate overheads/other implications of having a callback installed --- src/interfaces/libpq/fe-connect.c | 24 ++++++++++++++++++++++++ src/interfaces/libpq/libpq-events.c | 11 +++++++++++ src/interfaces/libpq/libpq-events.h | 10 +++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index a6a1db3356..ddc3f38cf1 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -452,7 +452,19 @@ pqDropConnection(PGconn *conn, bool flushInput) /* Close the socket itself */ if (conn->sock != PGINVALID_SOCKET) + { + /* Report that the socket is closing. */ + for (int i = 0; i < conn->nEvents; i++) + { + PGEventSocket evt; + + evt.conn = conn; + evt.socket = conn->sock; + (void) conn->events[i].proc(PGEVT_SOCKETCLOSE, &evt, + conn->events[i].passThrough); + } closesocket(conn->sock); + } conn->sock = PGINVALID_SOCKET; /* Optionally discard any unread data */ @@ -2576,6 +2588,18 @@ keep_going: /* We will come back to here until there is goto error_return; } + /* Report that a new socket has been created. */ + for (int i = 0; i < conn->nEvents; i++) + { + PGEventSocket evt; + + evt.conn = conn; + evt.socket = conn->sock; + (void) conn->events[i].proc(PGEVT_SOCKET, &evt, + conn->events[i].passThrough); + /* XXX check call result and fail */ + } + /* * Once we've identified a target address, all errors * except the preceding socket()-failure case should be diff --git a/src/interfaces/libpq/libpq-events.c b/src/interfaces/libpq/libpq-events.c index 7754c37748..2c549ec457 100644 --- a/src/interfaces/libpq/libpq-events.c +++ b/src/interfaces/libpq/libpq-events.c @@ -87,6 +87,17 @@ PQregisterEventProc(PGconn *conn, PGEventProc proc, return false; } + /* If we already have a socket, report a socket event immediately. */ + if (conn->sock != PGINVALID_SOCKET) + { + PGEventSocket evt; + + evt.conn = conn; + evt.socket = conn->sock; + (void) proc(PGEVT_SOCKET, &evt, passThrough); + /* XXX check return and fail (callback out of memory) */ + } + return true; } diff --git a/src/interfaces/libpq/libpq-events.h b/src/interfaces/libpq/libpq-events.h index d93b7c4d4e..da64dc866b 100644 --- a/src/interfaces/libpq/libpq-events.h +++ b/src/interfaces/libpq/libpq-events.h @@ -31,7 +31,9 @@ typedef enum PGEVT_CONNDESTROY, PGEVT_RESULTCREATE, PGEVT_RESULTCOPY, - PGEVT_RESULTDESTROY + PGEVT_RESULTDESTROY, + PGEVT_SOCKET, + PGEVT_SOCKETCLOSE } PGEventId; typedef struct @@ -66,6 +68,12 @@ typedef struct PGresult *result; } PGEventResultDestroy; +typedef struct +{ + PGconn *conn; + pgsocket socket; +} PGEventSocket; + typedef int (*PGEventProc) (PGEventId evtId, void *evtInfo, void *passThrough); /* Registers an event proc with the given PGconn. */ -- 2.33.1