int close_all_fds(const int except[], unsigned n_except) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; assert(n_except == 0 || except); d = opendir("/proc/self/fd"); if (!d) { int fd; struct rlimit rl; /* When /proc isn't available (for example in chroots) * the fallback is brute forcing through the fd * table */ assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0); for (fd = 3; fd < (int) rl.rlim_max; fd ++) { if (fd_in_set(fd, except, n_except)) continue; if (close_nointr(fd) < 0) if (errno != EBADF && r == 0) r = -errno; } return r; } while ((de = readdir(d))) { int fd = -1; if (hidden_file(de->d_name)) continue; if (safe_atoi(de->d_name, &fd) < 0) /* Let's better ignore this, just in case */ continue; if (fd < 3) continue; if (fd == dirfd(d)) continue; if (fd_in_set(fd, except, n_except)) continue; if (close_nointr(fd) < 0) { /* Valgrind has its own FD and doesn't want to have it closed */ if (errno != EBADF && r == 0) r = -errno; } } return r; }
static void test_close_nointr(void) { char name[] = "/tmp/test-test-close_nointr.XXXXXX"; int fd; fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(close_nointr(fd) >= 0); assert_se(close_nointr(fd) < 0); unlink(name); }
_public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) { int fd, k; bool good = false; assert_return(m, -EINVAL); fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (fd < 0) return -errno; if (!category || streq(category, "links")) { k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE); if (k < 0) { safe_close(fd); return -errno; } good = true; } if (!good) { close_nointr(fd); return -EINVAL; } *m = FD_TO_MONITOR(fd); return 0; }
static void test_fd_move_above_stdio(void) { int original_stdin, new_fd; original_stdin = fcntl(0, F_DUPFD, 3); assert_se(original_stdin >= 3); assert_se(close_nointr(0) != EBADF); new_fd = open("/dev/null", O_RDONLY); assert_se(new_fd == 0); new_fd = fd_move_above_stdio(new_fd); assert_se(new_fd >= 3); assert_se(dup(original_stdin) == 0); assert_se(close_nointr(original_stdin) != EBADF); assert_se(close_nointr(new_fd) != EBADF); }
_public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) { int fd; assert_return(m, NULL); fd = MONITOR_TO_FD(m); close_nointr(fd); return NULL; }
_public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) { int fd; if (m) { fd = MONITOR_TO_FD(m); close_nointr(fd); } return NULL; }
static void test_unlink_noerrno(void) { char name[] = "/tmp/test-close_nointr.XXXXXX"; int fd; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(close_nointr(fd) >= 0); { PROTECT_ERRNO; errno = -42; assert_se(unlink_noerrno(name) >= 0); assert_se(errno == -42); assert_se(unlink_noerrno(name) < 0); assert_se(errno == -42); } }
int asynchronous_close(int fd) { int r; /* This is supposed to behave similar to safe_close(), but * actually invoke close() asynchronously, so that it will * never block. Ideally the kernel would have an API for this, * but it doesn't, so we work around it, and hide this as a * far away as we can. */ if (fd >= 0) { PROTECT_ERRNO; r = asynchronous_job(close_thread, INT_TO_PTR(fd)); if (r < 0) assert_se(close_nointr(fd) != -EBADF); } return -1; }
/** * gs_file_sync_data: * @file: a #GFile * @cancellable: * @error: * * Wraps the UNIX fsync() function (or fdatasync(), if available), which * ensures that the data in @file is on non-volatile storage. */ gboolean gs_file_sync_data (GFile *file, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; int res; int fd = -1; if (!gs_file_openat_noatime (AT_FDCWD, gs_file_get_path_cached (file), &fd, cancellable, error)) goto out; do { #ifdef __linux res = fdatasync (fd); #else res = fsync (fd); #endif } while (G_UNLIKELY (res != 0 && errno == EINTR)); if (res != 0) { gs_set_prefix_error_from_errno (error, errno, "fdatasync"); goto out; } res = close_nointr (fd); if (res != 0) { gs_set_prefix_error_from_errno (error, errno, "close"); goto out; } fd = -1; ret = TRUE; out: if (fd != -1) close_nointr_noerror (fd); return ret; }
void fdset_free(FDSet *s) { void *p; while ((p = set_steal_first(MAKE_SET(s)))) { /* Valgrind's fd might have ended up in this set here, * due to fdset_new_fill(). We'll ignore all failures * here, so that the EBADFD that valgrind will return * us on close() doesn't influence us */ /* When reloading duplicates of the private bus * connection fds and suchlike are closed here, which * has no effect at all, since they are only * duplicates. So don't be surprised about these log * messages. */ log_debug("Closing left-over fd %i", PTR_TO_FD(p)); close_nointr(PTR_TO_FD(p)); } set_free(MAKE_SET(s)); }
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; }
static void *close_thread(void *p) { assert_se(close_nointr(PTR_TO_INT(p)) != -EBADF); return NULL; }
static void close_nointr_noerror (int fd) { (void) close_nointr (fd); }
static void *close_thread(void *p) { (void) pthread_setname_np(pthread_self(), "close"); assert_se(close_nointr(PTR_TO_FD(p)) != -EBADF); return NULL; }