/** * Closes all file descriptors greater or equal to ``first_fd''. */ void close_file_descriptors(const int first_fd) { int fd; g_return_if_fail(first_fd >= 0); if (try_close_from(first_fd)) return; fd = getdtablesize() - 1; while (fd >= first_fd) { #ifdef HAVE_GTKOSXAPPLICATION /* OS X doesn't allow fds being closed not opened by us. During * GUI initialisation a new kqueue fd is created for UI events. This * is visible to us as a fifo which we are not allowed to close. * Set close on exec on all fifo's so we won't leak any of our other * fifo's * -- JA 2011-11-28 */ if (is_a_fifo(fd)) set_close_on_exec(fd); else #endif /* OS X frowns upon random fds being closed --RAM 2011-11-13 */ if (fd_is_opened(fd)) { if (close(fd)) { #if defined(F_MAXFD) fd = fcntl(0, F_MAXFD); continue; #endif /* F_MAXFD */ } } fd--; } }
/** * Closes all file descriptors greater or equal to ``first_fd'', skipping * preserved ones if ``preserve'' is TRUE. */ static void fd_close_from_internal(const int first_fd, bool preserve) { int fd; g_return_if_fail(first_fd >= 0); if (!preserve && try_close_from(first_fd)) return; fd = getdtablesize() - 1; while (fd >= first_fd) { if (preserve && hset_contains(fd_preserved, int_to_pointer(fd))) goto next; #ifdef HAVE_GTKOSXAPPLICATION /* OS X doesn't allow fds being closed not opened by us. During * GUI initialisation a new kqueue fd is created for UI events. This * is visible to us as a fifo which we are not allowed to close. * Set close on exec on all fifo's so we won't leak any of our other * fifo's * -- JA 2011-11-28 */ if (is_a_fifo(fd)) fd_set_close_on_exec(fd); else #endif /* OS X frowns upon random fds being closed --RAM 2011-11-13 */ if (fd_is_opened(fd)) { if (close(fd)) { #if defined(F_MAXFD) fd = fcntl(0, F_MAXFD); continue; #endif /* F_MAXFD */ } } next: fd--; } /* * When called with a first_fd of 3, and we are on Windows, also make * sure we close all the known sockets we have. This lets the process * safely auto-restart, avoiding multiple listening sockets on the same * port. * --RAM, 2015-04-05 */ if ( is_running_on_mingw() && !preserve && 3 == first_fd && NULL != fd_sockets ) { hset_t *fds = fd_sockets; /* * We're about to exec() another process, and we may be crashing, * hence do not bother using hset_foreach_remove() to ensure minimal * processing. We also reset the fd_sockets pointer to NULL to * make sure s_close() will do nothing when fd_notify_socket_closed() * is called. */ fd_sockets = NULL; /* We don't expect race conditions here */ hset_foreach(fds, fd_socket_close, NULL); /* Don't bother freeing / clearing set, we're about to exec() */ } }