From b2cd05007396222fe66bbff371ca1b81fb1f4a15 Mon Sep 17 00:00:00 2001 From: Daniel28972897 Date: Tue, 28 Jul 2026 22:23:05 -0600 Subject: [PATCH] libudev: cache the errno for a failed parent lookup udev_device_get_parent() caches the result of device_new_from_parent() in udev_device->parent on first call. device_new_from_parent() sets errno correctly via return_with_errno() when it fails, so a caller gets the right errno on the first invocation. But on any subsequent call for the same object, the cached NULL is returned directly without recomputing anything, so errno reflects whatever happened in between rather than the original failure reason. Cache the errno alongside the parent pointer (new parent_errno field, zero-initialized like the rest of the struct via udev_device_new()'s compound literal) and restore it whenever the cached parent is NULL. --- src/libudev/libudev-device.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c index 22ff6075e85..0216d56ae32 100644 --- a/src/libudev/libudev-device.c +++ b/src/libudev/libudev-device.c @@ -38,6 +38,7 @@ struct udev_device { struct udev_device *parent; bool parent_set; + int parent_errno; struct udev_list *properties; uint64_t properties_generation; @@ -393,9 +394,12 @@ _public_ struct udev_device* udev_device_get_parent(struct udev_device *udev_dev if (!udev_device->parent_set) { udev_device->parent_set = true; udev_device->parent = device_new_from_parent(udev_device); + udev_device->parent_errno = udev_device->parent ? 0 : errno; } - /* TODO: errno will differ here in case parent == NULL */ + if (!udev_device->parent) + errno = udev_device->parent_errno; + return udev_device->parent; } -- 2.47.3