diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libudev/util.c | 24 | ||||
-rw-r--r-- | src/libudev/util.h | 2 | ||||
-rw-r--r-- | src/udev/udevd.c | 10 |
3 files changed, 30 insertions, 6 deletions
diff --git a/src/libudev/util.c b/src/libudev/util.c index 4796505a5c..cfdf848cce 100644 --- a/src/libudev/util.c +++ b/src/libudev/util.c @@ -154,6 +154,30 @@ void close_nointr_nofail(int fd) { assert_se(close_nointr(fd) == 0); } +int safe_close(int fd) { + + /* + * Like close_nointr() but cannot fail. Guarantees errno is + * unchanged. Is a NOP with negative fds passed, and returns + * -1, so that it can be used in this syntax: + * + * fd = safe_close(fd); + */ + + if (fd >= 0) { + PROTECT_ERRNO; + + /* The kernel might return pretty much any error code + * via close(), but the fd will be closed anyway. The + * only condition we want to check for here is whether + * the fd was invalid at all... */ + + assert_se(close_nointr(fd) != -EBADF); + } + + return -1; +} + int unlink_noerrno(const char *path) { PROTECT_ERRNO; int r; diff --git a/src/libudev/util.h b/src/libudev/util.h index a950f2658f..332dfb6207 100644 --- a/src/libudev/util.h +++ b/src/libudev/util.h @@ -124,6 +124,8 @@ static inline const char *startswith(const char *s, const char *prefix) { char *endswith(const char *s, const char *postfix) _pure_; int close_nointr(int fd); +int safe_close(int fd); + void close_nointr_nofail(int fd); int safe_atou(const char *s, unsigned *ret_u); diff --git a/src/udev/udevd.c b/src/udev/udevd.c index bcbb5d4d2c..b05907edb1 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -301,6 +301,7 @@ static void worker_new(struct event *event) if (fd_lock >= 0 && flock(fd_lock, LOCK_SH|LOCK_NB) < 0) { log_debug("Unable to flock(%s), skipping event handling: %m", udev_device_get_devnode(d)); err = -EWOULDBLOCK; + fd_lock = safe_close(fd_lock); goto skip; } } @@ -317,8 +318,7 @@ static void worker_new(struct event *event) udev_device_update_db(dev); } - if (fd_lock >= 0) - close(fd_lock); + safe_close(fd_lock); /* send processed event back to libudev listeners */ udev_monitor_send_device(worker_monitor, NULL, dev); @@ -377,10 +377,8 @@ skip: } out: udev_device_unref(dev); - if (fd_signal >= 0) - close(fd_signal); - if (fd_ep >= 0) - close(fd_ep); + safe_close(fd_signal); + safe_close(fd_ep); close(fd_inotify); close(worker_watch[WRITE_END]); udev_rules_unref(rules); |