2 * Copyright (C) 2008-2015 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include <sys/types.h>
28 #ifndef HAVE_CLOSEFROM
29 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
30 # include <sys/stat.h>
32 # include <sys/syscall.h>
33 /* This is from the kernel sources. We limit the length of directory names to
34 * 256 as we only use it to enumerate FDs. */
35 struct linux_dirent64
{
38 unsigned short d_reclen
;
42 #else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */
44 #endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */
48 #include <collections/enumerator.h>
50 #define FD_DIR "/proc/self/fd"
54 #include <threading/mutex.h>
55 #include <threading/condvar.h>
58 * Flag to indicate signaled wait_sigint()
60 static bool sigint_signaled
= FALSE
;
63 * Condvar to wait in wait_sigint()
65 static condvar_t
*sigint_cond
;
68 * Mutex to check signaling()
70 static mutex_t
*sigint_mutex
;
73 * Control handler to catch ^C
75 static BOOL WINAPI
handler(DWORD dwCtrlType
)
80 case CTRL_BREAK_EVENT
:
81 case CTRL_CLOSE_EVENT
:
82 sigint_mutex
->lock(sigint_mutex
);
83 sigint_signaled
= TRUE
;
84 sigint_cond
->signal(sigint_cond
);
85 sigint_mutex
->unlock(sigint_mutex
);
97 SetConsoleCtrlHandler(handler
, TRUE
);
99 sigint_mutex
= mutex_create(MUTEX_TYPE_DEFAULT
);
100 sigint_cond
= condvar_create(CONDVAR_TYPE_DEFAULT
);
102 sigint_mutex
->lock(sigint_mutex
);
103 while (!sigint_signaled
)
105 sigint_cond
->wait(sigint_cond
, sigint_mutex
);
107 sigint_mutex
->unlock(sigint_mutex
);
109 sigint_mutex
->destroy(sigint_mutex
);
110 sigint_cond
->destroy(sigint_cond
);
123 sigaddset(&set
, SIGINT
);
124 sigaddset(&set
, SIGTERM
);
126 sigprocmask(SIG_BLOCK
, &set
, NULL
);
127 sigwaitinfo(&set
, NULL
);
130 #ifndef HAVE_SIGWAITINFO
131 int sigwaitinfo(const sigset_t
*set
, void *info
)
136 { /* we don't replicate siginfo_t, fail if anybody tries to use it */
140 err
= sigwait(set
, &sig
);
148 #endif /* HAVE_SIGWAITINFO */
151 #ifndef HAVE_CLOSEFROM
153 * Described in header.
155 void closefrom(int low_fd
)
157 int max_fd
, dir_fd
, fd
;
159 /* try to close only open file descriptors on Linux... */
160 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
161 /* By directly using a syscall we avoid any calls that might be unsafe after
162 * fork() (e.g. malloc()). */
163 char buffer
[sizeof(struct linux_dirent64
)];
164 struct linux_dirent64
*entry
;
167 dir_fd
= open("/proc/self/fd", O_RDONLY
);
170 while ((len
= syscall(SYS_getdents64
, dir_fd
, buffer
,
171 sizeof(buffer
))) > 0)
173 for (offset
= 0; offset
< len
; offset
+= entry
->d_reclen
)
175 entry
= (struct linux_dirent64
*)(buffer
+ offset
);
176 if (!isdigit(entry
->d_name
[0]))
180 fd
= atoi(entry
->d_name
);
181 if (fd
!= dir_fd
&& fd
>= low_fd
)
190 #else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */
191 /* This is potentially unsafe when called after fork() in multi-threaded
192 * applications. In particular opendir() will require an allocation.
193 * Depends on how the malloc() implementation handles such situations. */
195 struct dirent
*entry
;
198 /* if we don't have dirfd() lets close the lowest FD and hope it gets reused
204 dir
= opendir(FD_DIR
);
210 while ((entry
= readdir(dir
)))
212 if (!isdigit(entry
->d_name
[0]))
216 fd
= atoi(entry
->d_name
);
217 if (fd
!= dir_fd
&& fd
>= low_fd
)
225 #endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */
227 /* ...fall back to closing all fds otherwise */
229 max_fd
= _getmaxstdio();
231 max_fd
= (int)sysconf(_SC_OPEN_MAX
);
237 for (fd
= low_fd
; fd
< max_fd
; fd
++)
242 #endif /* HAVE_CLOSEFROM */