From: David Marchand <david.marchand@redhat.com>
To: dev@dpdk.org, hkalra@marvell.com
Cc: Nipun Gupta <nipun.gupta@amd.com>,
Nikhil Agarwal <nikhil.agarwal@amd.com>,
Chenbo Xia <chenbox@nvidia.com>,
Anatoly Burakov <anatoly.burakov@intel.com>,
Long Li <longli@microsoft.com>, Wei Hu <weh@microsoft.com>,
Nithin Dabilpuram <ndabilpuram@marvell.com>,
Kiran Kumar K <kirankumark@marvell.com>,
Sunil Kumar Kori <skori@marvell.com>,
Satha Rao <skoteshwar@marvell.com>,
Jakub Grajciar <jgrajcia@cisco.com>,
Bruce Richardson <bruce.richardson@intel.com>
Subject: [RFC v3 4/5] interrupts: close interrupt FDs
Date: Mon, 7 Sep 2026 14:13:47 +0200 [thread overview]
Message-ID: <20260907121348.3049808-5-david.marchand@redhat.com> (raw)
In-Reply-To: <20260907121348.3049808-1-david.marchand@redhat.com>
Add rte_intr_fd_close() and rte_intr_dev_fd_close() helpers to
encapsulate the common pattern of closing an interrupt handle's
file descriptor and resetting it to -1.
This simplifies code in multiple drivers that previously had to:
if (rte_intr_fd_get(handle) >= 0) {
close(rte_intr_fd_get(handle));
rte_intr_fd_set(handle, -1);
}
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
Changes since RFC v2:
- added unit test,
- converted bus/cdx and FreeBSD EAL interrupt code,
- added wrappers for common/cnxk,
---
app/test/test_interrupts.c | 72 ++++++++++++++++++++++++++
doc/guides/rel_notes/release_26_11.rst | 2 +
drivers/bus/cdx/cdx_vfio.c | 6 +--
drivers/bus/pci/bsd/pci.c | 7 +--
drivers/bus/pci/linux/pci_uio.c | 15 ++----
drivers/bus/pci/linux/pci_vfio.c | 16 ++----
drivers/bus/pci/pci_common_uio.c | 12 +----
drivers/bus/vmbus/linux/vmbus_uio.c | 13 ++---
drivers/bus/vmbus/vmbus_common_uio.c | 11 +---
drivers/common/cnxk/roc_platform.h | 2 +
drivers/net/memif/memif_socket.c | 13 ++---
lib/eal/common/eal_common_interrupts.c | 23 ++++++++
lib/eal/freebsd/eal_alarm.c | 3 +-
lib/eal/include/rte_interrupts.h | 27 ++++++++++
lib/eal/linux/eal_dev.c | 5 +-
15 files changed, 147 insertions(+), 80 deletions(-)
diff --git a/app/test/test_interrupts.c b/app/test/test_interrupts.c
index 747dfc4f48..67f1e6429a 100644
--- a/app/test/test_interrupts.c
+++ b/app/test/test_interrupts.c
@@ -169,6 +169,65 @@ test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l,
return 0;
}
+/**
+ * Tests for rte_intr_fd_close() and rte_intr_dev_fd_close().
+ */
+static int
+test_interrupt_close(void)
+{
+ struct rte_intr_handle *intr_handle;
+ int pipefd[2];
+
+ /* check with null intr_handle */
+ rte_intr_fd_close(NULL);
+ rte_intr_dev_fd_close(NULL);
+
+ intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
+ if (!intr_handle)
+ return -1;
+
+ if (pipe(pipefd) < 0) {
+ rte_intr_instance_free(intr_handle);
+ return -1;
+ }
+
+ if (rte_intr_fd_set(intr_handle, pipefd[0]) < 0 ||
+ rte_intr_dev_fd_set(intr_handle, pipefd[1]) < 0) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ rte_intr_instance_free(intr_handle);
+ return -1;
+ }
+
+ /* check rte_intr_fd_close */
+ rte_intr_fd_close(intr_handle);
+
+ if (rte_intr_fd_get(intr_handle) != -1) {
+ printf("fd not set to -1 after close\n");
+ close(pipefd[1]);
+ rte_intr_instance_free(intr_handle);
+ return -1;
+ }
+
+ /* calling again should be a noop */
+ rte_intr_fd_close(intr_handle);
+
+ /* check rte_intr_dev_fd_close */
+ rte_intr_dev_fd_close(intr_handle);
+
+ if (rte_intr_dev_fd_get(intr_handle) != -1) {
+ printf("dev_fd not set to -1 after close\n");
+ rte_intr_instance_free(intr_handle);
+ return -1;
+ }
+
+ /* calling again should be a noop */
+ rte_intr_dev_fd_close(intr_handle);
+
+ rte_intr_instance_free(intr_handle);
+ return 0;
+}
+
#else
/* to be implemented for bsd later */
static inline int
@@ -206,6 +265,12 @@ test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l,
return 0;
}
+
+static int
+test_interrupt_close(void)
+{
+ return 0;
+}
#endif /* RTE_EXEC_ENV_LINUX */
/**
@@ -566,6 +631,13 @@ test_interrupt(void)
}
rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
+ printf("start interrupt close test\n");
+ if (test_interrupt_close() < 0) {
+ printf("fail to check interrupt close\n");
+ goto out;
+ }
+ rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
+
ret = 0;
out:
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 36d6f3a05f..07b90f1529 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -99,6 +99,8 @@ API Changes
* ``rte_intr_instance_alloc()`` now initializes file descriptors
to invalid values instead of zero.
+ * Added ``rte_intr_fd_close()`` and ``rte_intr_dev_fd_close()``
+ helpers to close file descriptors and reset them to -1.
ABI Changes
diff --git a/drivers/bus/cdx/cdx_vfio.c b/drivers/bus/cdx/cdx_vfio.c
index 0e4af4e940..8d67058bfe 100644
--- a/drivers/bus/cdx/cdx_vfio.c
+++ b/drivers/bus/cdx/cdx_vfio.c
@@ -110,11 +110,7 @@ cdx_vfio_unmap_resource_primary(struct rte_cdx_device *dev)
CDX_BUS_ERR("Error when disabling bus master for %s",
dev->device.name);
- if (close(rte_intr_fd_get(dev->intr_handle)) < 0) {
- CDX_BUS_ERR("Error when closing eventfd file descriptor for %s",
- dev->device.name);
- return -1;
- }
+ rte_intr_fd_close(dev->intr_handle);
}
vfio_dev_fd = rte_intr_dev_fd_get(dev->intr_handle);
diff --git a/drivers/bus/pci/bsd/pci.c b/drivers/bus/pci/bsd/pci.c
index bbe08605af..f1012bb91b 100644
--- a/drivers/bus/pci/bsd/pci.c
+++ b/drivers/bus/pci/bsd/pci.c
@@ -93,11 +93,8 @@ pci_uio_free_resource(struct rte_pci_device *dev,
{
rte_free(uio_res);
- if (rte_intr_fd_get(dev->intr_handle) >= 0) {
- close(rte_intr_fd_get(dev->intr_handle));
- rte_intr_fd_set(dev->intr_handle, -1);
- rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);
- }
+ rte_intr_fd_close(dev->intr_handle);
+ rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);
}
int
diff --git a/drivers/bus/pci/linux/pci_uio.c b/drivers/bus/pci/linux/pci_uio.c
index 40e96b1c67..0983474994 100644
--- a/drivers/bus/pci/linux/pci_uio.c
+++ b/drivers/bus/pci/linux/pci_uio.c
@@ -197,20 +197,11 @@ void
pci_uio_free_resource(struct rte_pci_device *dev,
struct mapped_pci_resource *uio_res)
{
- int uio_cfg_fd = rte_intr_dev_fd_get(dev->intr_handle);
-
rte_free(uio_res);
- if (uio_cfg_fd >= 0) {
- close(uio_cfg_fd);
- rte_intr_dev_fd_set(dev->intr_handle, -1);
- }
-
- if (rte_intr_fd_get(dev->intr_handle) >= 0) {
- close(rte_intr_fd_get(dev->intr_handle));
- rte_intr_fd_set(dev->intr_handle, -1);
- rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);
- }
+ rte_intr_dev_fd_close(dev->intr_handle);
+ rte_intr_fd_close(dev->intr_handle);
+ rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);
}
int
diff --git a/drivers/bus/pci/linux/pci_vfio.c b/drivers/bus/pci/linux/pci_vfio.c
index a92a0d86ec..84c338c68e 100644
--- a/drivers/bus/pci/linux/pci_vfio.c
+++ b/drivers/bus/pci/linux/pci_vfio.c
@@ -354,9 +354,7 @@ pci_vfio_enable_notifier(struct rte_pci_device *dev, int vfio_dev_fd)
return 0;
error:
- close(fd);
-
- rte_intr_fd_set(dev->vfio_req_intr_handle, -1);
+ rte_intr_fd_close(dev->vfio_req_intr_handle);
rte_intr_type_set(dev->vfio_req_intr_handle, RTE_INTR_HANDLE_UNKNOWN);
rte_intr_dev_fd_set(dev->vfio_req_intr_handle, -1);
@@ -383,9 +381,7 @@ pci_vfio_disable_notifier(struct rte_pci_device *dev)
return -1;
}
- close(rte_intr_fd_get(dev->vfio_req_intr_handle));
-
- rte_intr_fd_set(dev->vfio_req_intr_handle, -1);
+ rte_intr_fd_close(dev->vfio_req_intr_handle);
rte_intr_type_set(dev->vfio_req_intr_handle, RTE_INTR_HANDLE_UNKNOWN);
rte_intr_dev_fd_set(dev->vfio_req_intr_handle, -1);
@@ -1073,13 +1069,7 @@ pci_vfio_unmap_resource_primary(struct rte_pci_device *dev)
return -1;
}
- if (rte_intr_fd_get(dev->intr_handle) < 0)
- return -1;
-
- if (close(rte_intr_fd_get(dev->intr_handle)) < 0) {
- PCI_LOG(INFO, "Error when closing eventfd file descriptor for %s", pci_addr);
- return -1;
- }
+ rte_intr_fd_close(dev->intr_handle);
vfio_dev_fd = rte_intr_dev_fd_get(dev->intr_handle);
if (vfio_dev_fd < 0)
diff --git a/drivers/bus/pci/pci_common_uio.c b/drivers/bus/pci/pci_common_uio.c
index 47d50721dc..52a10f806a 100644
--- a/drivers/bus/pci/pci_common_uio.c
+++ b/drivers/bus/pci/pci_common_uio.c
@@ -211,7 +211,6 @@ pci_uio_unmap_resource(struct rte_pci_device *dev)
struct mapped_pci_resource *uio_res;
struct mapped_pci_res_list *uio_res_list =
RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list);
- int uio_cfg_fd;
if (dev == NULL)
return;
@@ -222,15 +221,8 @@ pci_uio_unmap_resource(struct rte_pci_device *dev)
return;
/* close fd */
- if (rte_intr_fd_get(dev->intr_handle) >= 0)
- close(rte_intr_fd_get(dev->intr_handle));
- uio_cfg_fd = rte_intr_dev_fd_get(dev->intr_handle);
- if (uio_cfg_fd >= 0) {
- close(uio_cfg_fd);
- rte_intr_dev_fd_set(dev->intr_handle, -1);
- }
-
- rte_intr_fd_set(dev->intr_handle, -1);
+ rte_intr_fd_close(dev->intr_handle);
+ rte_intr_dev_fd_close(dev->intr_handle);
rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);
/* secondary processes - just free maps */
diff --git a/drivers/bus/vmbus/linux/vmbus_uio.c b/drivers/bus/vmbus/linux/vmbus_uio.c
index fbafc5027d..c52d6738a5 100644
--- a/drivers/bus/vmbus/linux/vmbus_uio.c
+++ b/drivers/bus/vmbus/linux/vmbus_uio.c
@@ -67,16 +67,9 @@ vmbus_uio_free_resource(struct rte_vmbus_device *dev,
{
rte_free(uio_res);
- if (rte_intr_dev_fd_get(dev->intr_handle) >= 0) {
- close(rte_intr_dev_fd_get(dev->intr_handle));
- rte_intr_dev_fd_set(dev->intr_handle, -1);
- }
-
- if (rte_intr_fd_get(dev->intr_handle) >= 0) {
- close(rte_intr_fd_get(dev->intr_handle));
- rte_intr_fd_set(dev->intr_handle, -1);
- rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);
- }
+ rte_intr_dev_fd_close(dev->intr_handle);
+ rte_intr_fd_close(dev->intr_handle);
+ rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);
}
int
diff --git a/drivers/bus/vmbus/vmbus_common_uio.c b/drivers/bus/vmbus/vmbus_common_uio.c
index 7459f4ea7a..9765f5f609 100644
--- a/drivers/bus/vmbus/vmbus_common_uio.c
+++ b/drivers/bus/vmbus/vmbus_common_uio.c
@@ -254,14 +254,7 @@ vmbus_uio_unmap_resource(struct rte_vmbus_device *dev)
rte_free(uio_res);
/* close fd */
- if (rte_intr_fd_get(dev->intr_handle) >= 0)
- close(rte_intr_fd_get(dev->intr_handle));
-
- if (rte_intr_dev_fd_get(dev->intr_handle) >= 0) {
- close(rte_intr_dev_fd_get(dev->intr_handle));
- rte_intr_dev_fd_set(dev->intr_handle, -1);
- }
-
- rte_intr_fd_set(dev->intr_handle, -1);
+ rte_intr_fd_close(dev->intr_handle);
+ rte_intr_dev_fd_close(dev->intr_handle);
rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);
}
diff --git a/drivers/common/cnxk/roc_platform.h b/drivers/common/cnxk/roc_platform.h
index ac4f76473f..aba9782023 100644
--- a/drivers/common/cnxk/roc_platform.h
+++ b/drivers/common/cnxk/roc_platform.h
@@ -171,8 +171,10 @@ plt_thread_is_valid(plt_thread_t thr)
#define plt_intr_vec_list_free rte_intr_vec_list_free
#define plt_intr_fd_set rte_intr_fd_set
#define plt_intr_fd_get rte_intr_fd_get
+#define plt_intr_fd_close rte_intr_fd_close
#define plt_intr_dev_fd_get rte_intr_dev_fd_get
#define plt_intr_dev_fd_set rte_intr_dev_fd_set
+#define plt_intr_dev_fd_close rte_intr_dev_fd_close
#define plt_intr_type_get rte_intr_type_get
#define plt_intr_type_set rte_intr_type_set
#define plt_intr_instance_alloc rte_intr_instance_alloc
diff --git a/drivers/net/memif/memif_socket.c b/drivers/net/memif/memif_socket.c
index 649f8d0e61..94cd70fb89 100644
--- a/drivers/net/memif/memif_socket.c
+++ b/drivers/net/memif/memif_socket.c
@@ -510,8 +510,7 @@ memif_intr_unregister_handler(struct rte_intr_handle *intr_handle, void *arg)
struct memif_control_channel *cc = arg;
/* close control channel fd */
- if (rte_intr_fd_get(intr_handle) >= 0)
- close(rte_intr_fd_get(intr_handle));
+ rte_intr_fd_close(intr_handle);
/* clear message queue */
while ((elt = TAILQ_FIRST(&cc->msg_queue)) != NULL) {
TAILQ_REMOVE(&cc->msg_queue, elt, next);
@@ -596,10 +595,7 @@ memif_disconnect(struct rte_eth_dev *dev)
continue;
}
- if (rte_intr_fd_get(mq->intr_handle) > 0) {
- close(rte_intr_fd_get(mq->intr_handle));
- rte_intr_fd_set(mq->intr_handle, -1);
- }
+ rte_intr_fd_close(mq->intr_handle);
}
for (i = 0; i < pmd->cfg.num_s2c_rings; i++) {
if (pmd->role == MEMIF_ROLE_SERVER) {
@@ -614,10 +610,7 @@ memif_disconnect(struct rte_eth_dev *dev)
continue;
}
- if (rte_intr_fd_get(mq->intr_handle) > 0) {
- close(rte_intr_fd_get(mq->intr_handle));
- rte_intr_fd_set(mq->intr_handle, -1);
- }
+ rte_intr_fd_close(mq->intr_handle);
}
memif_free_regions(dev);
diff --git a/lib/eal/common/eal_common_interrupts.c b/lib/eal/common/eal_common_interrupts.c
index 4e31a71319..8176eb089a 100644
--- a/lib/eal/common/eal_common_interrupts.c
+++ b/lib/eal/common/eal_common_interrupts.c
@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <rte_errno.h>
#include <rte_interrupts.h>
@@ -219,6 +220,17 @@ int rte_intr_fd_get(const struct rte_intr_handle *intr_handle)
return -1;
}
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_intr_fd_close, 26.11)
+void rte_intr_fd_close(struct rte_intr_handle *intr_handle)
+{
+ int fd = rte_intr_fd_get(intr_handle);
+
+ if (fd >= 0) {
+ close(fd);
+ rte_intr_fd_set(intr_handle, -1);
+ }
+}
+
RTE_EXPORT_SYMBOL(rte_intr_type_set)
int rte_intr_type_set(struct rte_intr_handle *intr_handle,
enum rte_intr_handle_type type)
@@ -265,6 +277,17 @@ int rte_intr_dev_fd_get(const struct rte_intr_handle *intr_handle)
return -1;
}
+RTE_EXPORT_INTERNAL_SYMBOL(rte_intr_dev_fd_close)
+void rte_intr_dev_fd_close(struct rte_intr_handle *intr_handle)
+{
+ int fd = rte_intr_dev_fd_get(intr_handle);
+
+ if (fd >= 0) {
+ close(fd);
+ rte_intr_dev_fd_set(intr_handle, -1);
+ }
+}
+
RTE_EXPORT_INTERNAL_SYMBOL(rte_intr_max_intr_set)
int rte_intr_max_intr_set(struct rte_intr_handle *intr_handle,
int max_intr)
diff --git a/lib/eal/freebsd/eal_alarm.c b/lib/eal/freebsd/eal_alarm.c
index c563ee9cc2..2697921760 100644
--- a/lib/eal/freebsd/eal_alarm.c
+++ b/lib/eal/freebsd/eal_alarm.c
@@ -54,8 +54,7 @@ rte_eal_alarm_cleanup(void)
int ret = rte_intr_callback_unregister_sync(intr_handle,
eal_alarm_callback, (void *)-1);
if (ret >= 0) {
- close(rte_intr_fd_get(intr_handle));
- rte_intr_fd_set(intr_handle, -1);
+ rte_intr_fd_close(intr_handle);
rte_intr_instance_free(intr_handle);
intr_handle = NULL;
}
diff --git a/lib/eal/include/rte_interrupts.h b/lib/eal/include/rte_interrupts.h
index 1cfb9d3f8e..d04c0c7b15 100644
--- a/lib/eal/include/rte_interrupts.h
+++ b/lib/eal/include/rte_interrupts.h
@@ -279,6 +279,19 @@ rte_intr_fd_set(struct rte_intr_handle *intr_handle, int fd);
int
rte_intr_fd_get(const struct rte_intr_handle *intr_handle);
+/**
+ * Close the FD of the given interrupt handle instance,
+ * and set FD to -1.
+ *
+ * If FD is not valid (< 0), nothing is done.
+ *
+ * @param intr_handle
+ * pointer to the interrupt handle.
+ */
+__rte_experimental
+void
+rte_intr_fd_close(struct rte_intr_handle *intr_handle);
+
/**
* Set the type field of interrupt handle with user provided
* interrupt type.
@@ -467,6 +480,20 @@ __rte_internal
int
rte_intr_dev_fd_get(const struct rte_intr_handle *intr_handle);
+/**
+ * @internal
+ * Close the device FD of the given interrupt handle instance,
+ * and set device FD to -1.
+ *
+ * If device FD is not valid (< 0), nothing is done.
+ *
+ * @param intr_handle
+ * pointer to the interrupt handle.
+ */
+__rte_internal
+void
+rte_intr_dev_fd_close(struct rte_intr_handle *intr_handle);
+
/**
* @internal
* Set the max intr field of interrupt handle with user
diff --git a/lib/eal/linux/eal_dev.c b/lib/eal/linux/eal_dev.c
index c78e565427..4f55dcc4e7 100644
--- a/lib/eal/linux/eal_dev.c
+++ b/lib/eal/linux/eal_dev.c
@@ -217,10 +217,7 @@ static void
dev_delayed_unregister(void *param)
{
rte_intr_callback_unregister(intr_handle, dev_uev_handler, param);
- if (rte_intr_fd_get(intr_handle) >= 0) {
- close(rte_intr_fd_get(intr_handle));
- rte_intr_fd_set(intr_handle, -1);
- }
+ rte_intr_fd_close(intr_handle);
}
static void
--
2.54.0
next prev parent reply other threads:[~2026-09-07 12:14 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-07 12:13 [RFC v3 0/5] Interrupts API update David Marchand
2026-09-07 12:13 ` [RFC v3 1/5] vdpa/mlx5: fix check on err interrupt FD David Marchand
2026-09-07 12:13 ` [RFC v3 2/5] eal/freebsd: fix a FD leak in the alarm subsystem David Marchand
2026-09-07 12:35 ` Bruce Richardson
2026-09-07 12:47 ` David Marchand
2026-09-07 12:13 ` [RFC v3 3/5] interrupts: mark file descriptors invalid on allocation David Marchand
2026-09-07 12:13 ` David Marchand [this message]
2026-09-07 12:13 ` [RFC v3 5/5] interrupts: warn on leaked file descriptors David Marchand
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260907121348.3049808-5-david.marchand@redhat.com \
--to=david.marchand@redhat.com \
--cc=anatoly.burakov@intel.com \
--cc=bruce.richardson@intel.com \
--cc=chenbox@nvidia.com \
--cc=dev@dpdk.org \
--cc=hkalra@marvell.com \
--cc=jgrajcia@cisco.com \
--cc=kirankumark@marvell.com \
--cc=longli@microsoft.com \
--cc=ndabilpuram@marvell.com \
--cc=nikhil.agarwal@amd.com \
--cc=nipun.gupta@amd.com \
--cc=skori@marvell.com \
--cc=skoteshwar@marvell.com \
--cc=weh@microsoft.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).