ipa: Allow signalling fd destroyed in ipa_server_conn_read
Similar to what we do in other osmo_fd cb, check for read_cb returning
-EBADF and in that case don't attempt using the osmo_fd anymore, either
because the fd was already closed (no need to then signal WRITE) or
because osmo_fd struct itself has been freed.
Change-Id: I4b968b72285f23a9552519cea67398a43d5003d2
diff --git a/include/osmocom/abis/ipa.h b/include/osmocom/abis/ipa.h
index 4359268..a738156 100644
--- a/include/osmocom/abis/ipa.h
+++ b/include/osmocom/abis/ipa.h
@@ -37,6 +37,7 @@
int (*closed_cb)(struct ipa_server_conn *peer);
int (*ccm_cb)(struct ipa_server_conn *peer, struct msgb *msg,
struct tlv_parsed *tlvp, struct ipaccess_unit *ud);
+ /* Callback when ofd has something to be read. -EBADF must be returned if the osmo_fd is destroyed. */
int (*cb)(struct ipa_server_conn *peer, struct msgb *msg);
void *data;
struct msgb *pending_msg;
diff --git a/src/input/ipa.c b/src/input/ipa.c
index d0363e2..09e3426 100644
--- a/src/input/ipa.c
+++ b/src/input/ipa.c
@@ -328,7 +328,7 @@
close(link->ofd.fd);
}
-static void ipa_server_conn_read(struct ipa_server_conn *conn)
+static int ipa_server_conn_read(struct ipa_server_conn *conn)
{
struct osmo_fd *ofd = &conn->ofd;
struct msgb *msg;
@@ -339,18 +339,18 @@
ret = ipa_msg_recv_buffered(ofd->fd, &msg, &conn->pending_msg);
if (ret <= 0) {
if (ret == -EAGAIN)
- return;
+ return 0;
else if (ret == -EPIPE || ret == -ECONNRESET)
LOGIPA(conn, LOGL_ERROR, "lost connection with server\n");
else if (ret == 0)
LOGIPA(conn, LOGL_ERROR, "connection closed with server\n");
ipa_server_conn_destroy(conn);
- return;
+ return -EBADF;
}
if (conn->cb)
- conn->cb(conn, msg);
+ return conn->cb(conn, msg);
- return;
+ return 0;
}
static void ipa_server_conn_write(struct ipa_server_conn *conn)
@@ -376,11 +376,12 @@
static int ipa_server_conn_cb(struct osmo_fd *ofd, unsigned int what)
{
struct ipa_server_conn *conn = ofd->data;
+ int rc = 0;
LOGP(DLINP, LOGL_DEBUG, "connected read/write\n");
if (what & BSC_FD_READ)
- ipa_server_conn_read(conn);
- if (what & BSC_FD_WRITE)
+ rc = ipa_server_conn_read(conn);
+ if (rc != -EBADF && (what & BSC_FD_WRITE))
ipa_server_conn_write(conn);
return 0;