Qt 4.8
qcore_unix_p.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #ifndef QCORE_UNIX_P_H
43 #define QCORE_UNIX_P_H
44 
45 //
46 // W A R N I N G
47 // -------------
48 //
49 // This file is not part of the Qt API. It exists for the convenience
50 // of Qt code on Unix. This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55 
56 #include "qplatformdefs.h"
57 #include "qatomic.h"
58 
59 #ifndef Q_OS_UNIX
60 # error "qcore_unix_p.h included on a non-Unix system"
61 #endif
62 
63 #include <string.h>
64 #include <sys/types.h>
65 #include <sys/stat.h>
66 #include <unistd.h>
67 
68 #include <sys/wait.h>
69 #include <errno.h>
70 #include <fcntl.h>
71 
72 #if defined(Q_OS_VXWORKS)
73 # include <ioLib.h>
74 #endif
75 
76 struct sockaddr;
77 
78 #if defined(Q_OS_LINUX) && defined(O_CLOEXEC)
79 # define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 1
81 namespace QtLibcSupplement {
82  inline int accept4(int, sockaddr *, QT_SOCKLEN_T *, int)
83  { errno = ENOSYS; return -1; }
84  inline int dup3(int, int, int)
85  { errno = ENOSYS; return -1; }
86  inline int pipe2(int [], int )
87  { errno = ENOSYS; return -1; }
88 }
90 using namespace QT_PREPEND_NAMESPACE(QtLibcSupplement);
91 
92 #else
93 # define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 0
94 #endif
95 
96 #define EINTR_LOOP(var, cmd) \
97  do { \
98  var = cmd; \
99  } while (var == -1 && errno == EINTR)
100 
102 
103 // Internal operator functions for timevals
104 inline timeval &normalizedTimeval(timeval &t)
105 {
106  while (t.tv_usec > 1000000l) {
107  ++t.tv_sec;
108  t.tv_usec -= 1000000l;
109  }
110  while (t.tv_usec < 0l) {
111  --t.tv_sec;
112  t.tv_usec += 1000000l;
113  }
114  return t;
115 }
116 inline bool operator<(const timeval &t1, const timeval &t2)
117 { return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec); }
118 inline bool operator==(const timeval &t1, const timeval &t2)
119 { return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec; }
120 inline timeval &operator+=(timeval &t1, const timeval &t2)
121 {
122  t1.tv_sec += t2.tv_sec;
123  t1.tv_usec += t2.tv_usec;
124  return normalizedTimeval(t1);
125 }
126 inline timeval operator+(const timeval &t1, const timeval &t2)
127 {
128  timeval tmp;
129  tmp.tv_sec = t1.tv_sec + t2.tv_sec;
130  tmp.tv_usec = t1.tv_usec + t2.tv_usec;
131  return normalizedTimeval(tmp);
132 }
133 inline timeval operator-(const timeval &t1, const timeval &t2)
134 {
135  timeval tmp;
136  tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1);
137  tmp.tv_usec = t1.tv_usec - (t2.tv_usec + 1000000);
138  return normalizedTimeval(tmp);
139 }
140 inline timeval operator*(const timeval &t1, int mul)
141 {
142  timeval tmp;
143  tmp.tv_sec = t1.tv_sec * mul;
144  tmp.tv_usec = t1.tv_usec * mul;
145  return normalizedTimeval(tmp);
146 }
147 
148 inline void qt_ignore_sigpipe()
149 {
150 #ifndef Q_NO_POSIX_SIGNALS
151  // Set to ignore SIGPIPE once only.
153  if (!atom) {
154  // More than one thread could turn off SIGPIPE at the same time
155  // But that's acceptable because they all would be doing the same
156  // action
157  struct sigaction noaction;
158  memset(&noaction, 0, sizeof(noaction));
159  noaction.sa_handler = SIG_IGN;
160  ::sigaction(SIGPIPE, &noaction, 0);
161  atom = 1;
162  }
163 #else
164  // Posix signals are not supported by the underlying platform
165  // so we don't need to ignore sigpipe signal explicitly
166 #endif
167 }
168 
169 // don't call QT_OPEN or ::open
170 // call qt_safe_open
171 static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777)
172 {
173 #ifdef O_CLOEXEC
174  flags |= O_CLOEXEC;
175 #endif
176  register int fd;
177  EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode));
178 
179  // unknown flags are ignored, so we have no way of verifying if
180  // O_CLOEXEC was accepted
181  if (fd != -1)
182  ::fcntl(fd, F_SETFD, FD_CLOEXEC);
183  return fd;
184 }
185 #undef QT_OPEN
186 #define QT_OPEN qt_safe_open
187 
188 #ifndef Q_OS_VXWORKS // no POSIX pipes in VxWorks
189 // don't call ::pipe
190 // call qt_safe_pipe
191 static inline int qt_safe_pipe(int pipefd[2], int flags = 0)
192 {
193 #ifdef O_CLOEXEC
194  Q_ASSERT((flags & ~(O_CLOEXEC | O_NONBLOCK)) == 0);
195 #else
196  Q_ASSERT((flags & ~O_NONBLOCK) == 0);
197 #endif
198 
199  register int ret;
200 #if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC)
201  // use pipe2
202  flags |= O_CLOEXEC;
203  ret = ::pipe2(pipefd, flags); // pipe2 is Linux-specific and is documented not to return EINTR
204  if (ret == 0 || errno != ENOSYS)
205  return ret;
206 #endif
207 
208  ret = ::pipe(pipefd);
209  if (ret == -1)
210  return -1;
211 
212  ::fcntl(pipefd[0], F_SETFD, FD_CLOEXEC);
213  ::fcntl(pipefd[1], F_SETFD, FD_CLOEXEC);
214 
215  // set non-block too?
216  if (flags & O_NONBLOCK) {
217  ::fcntl(pipefd[0], F_SETFL, ::fcntl(pipefd[0], F_GETFL) | O_NONBLOCK);
218  ::fcntl(pipefd[1], F_SETFL, ::fcntl(pipefd[1], F_GETFL) | O_NONBLOCK);
219  }
220 
221  return 0;
222 }
223 
224 #endif // Q_OS_VXWORKS
225 
226 // don't call dup or fcntl(F_DUPFD)
227 static inline int qt_safe_dup(int oldfd, int atleast = 0, int flags = FD_CLOEXEC)
228 {
229  Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
230 
231  register int ret;
232 #ifdef F_DUPFD_CLOEXEC
233  // use this fcntl
234  if (flags & FD_CLOEXEC) {
235  ret = ::fcntl(oldfd, F_DUPFD_CLOEXEC, atleast);
236  if (ret != -1 || errno != EINVAL)
237  return ret;
238  }
239 #endif
240 
241  // use F_DUPFD
242  ret = ::fcntl(oldfd, F_DUPFD, atleast);
243 
244  if (flags && ret != -1)
245  ::fcntl(ret, F_SETFD, flags);
246  return ret;
247 }
248 
249 // don't call dup2
250 // call qt_safe_dup2
251 static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC)
252 {
253  Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
254 
255  register int ret;
256 #if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC)
257  // use dup3
258  if (flags & FD_CLOEXEC) {
259  EINTR_LOOP(ret, ::dup3(oldfd, newfd, O_CLOEXEC));
260  if (ret == 0 || errno != ENOSYS)
261  return ret;
262  }
263 #endif
264  EINTR_LOOP(ret, ::dup2(oldfd, newfd));
265  if (ret == -1)
266  return -1;
267 
268  if (flags)
269  ::fcntl(newfd, F_SETFD, flags);
270  return 0;
271 }
272 
273 static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
274 {
275  qint64 ret = 0;
276  EINTR_LOOP(ret, QT_READ(fd, data, maxlen));
277  return ret;
278 }
279 #undef QT_READ
280 #define QT_READ qt_safe_read
281 
282 static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
283 {
284  qint64 ret = 0;
285  EINTR_LOOP(ret, QT_WRITE(fd, data, len));
286  return ret;
287 }
288 #undef QT_WRITE
289 #define QT_WRITE qt_safe_write
290 
291 static inline qint64 qt_safe_write_nosignal(int fd, const void *data, qint64 len)
292 {
294  return qt_safe_write(fd, data, len);
295 }
296 
297 static inline int qt_safe_close(int fd)
298 {
299  register int ret;
300  EINTR_LOOP(ret, QT_CLOSE(fd));
301  return ret;
302 }
303 #undef QT_CLOSE
304 #define QT_CLOSE qt_safe_close
305 
306 // - Open C does not (yet?) implement these on Symbian OS
307 // - VxWorks doesn't have processes
308 #if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_VXWORKS)
309 static inline int qt_safe_execve(const char *filename, char *const argv[],
310  char *const envp[])
311 {
312  register int ret;
313  EINTR_LOOP(ret, ::execve(filename, argv, envp));
314  return ret;
315 }
316 
317 static inline int qt_safe_execv(const char *path, char *const argv[])
318 {
319  register int ret;
320  EINTR_LOOP(ret, ::execv(path, argv));
321  return ret;
322 }
323 
324 static inline int qt_safe_execvp(const char *file, char *const argv[])
325 {
326  register int ret;
327  EINTR_LOOP(ret, ::execvp(file, argv));
328  return ret;
329 }
330 #endif
331 
332 #ifndef Q_OS_VXWORKS // no processes on VxWorks
333 static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
334 {
335  register int ret;
336  EINTR_LOOP(ret, ::waitpid(pid, status, options));
337  return ret;
338 }
339 
340 #endif // Q_OS_VXWORKS
341 
342 #if !defined(_POSIX_MONOTONIC_CLOCK)
343 # define _POSIX_MONOTONIC_CLOCK -1
344 #endif
345 
346 timeval qt_gettime(); // in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp
347 
348 Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
349  const struct timeval *tv);
350 
351 // according to X/OPEN we have to define semun ourselves
352 // we use prefix as on some systems sem.h will have it
353 struct semid_ds;
354 union qt_semun {
355  int val; /* value for SETVAL */
356  struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
357  unsigned short *array; /* array for GETALL, SETALL */
358 };
359 
361 
362 #endif
timeval operator-(const timeval &t1, const timeval &t2)
Definition: qcore_unix_p.h:133
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
#define EINTR_LOOP(var, cmd)
Definition: qcore_unix_p.h:96
static int qt_safe_execvp(const char *file, char *const argv[])
Definition: qcore_unix_p.h:324
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
static int qt_safe_close(int fd)
Definition: qcore_unix_p.h:297
struct semid_ds * buf
Definition: qcore_unix_p.h:356
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
#define Q_BASIC_ATOMIC_INITIALIZER(a)
Definition: qbasicatomic.h:218
Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, const struct timeval *tv)
Definition: qcore_unix.cpp:73
#define QT_READ
Definition: qcore_unix_p.h:280
#define QT_SOCKLEN_T
int mode_t
static int qt_safe_execve(const char *filename, char *const argv[], char *const envp[])
Definition: qcore_unix_p.h:309
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void qt_ignore_sigpipe()
Definition: qcore_unix_p.h:148
static int qt_safe_open(const char *pathname, int flags, mode_t mode=0777)
Definition: qcore_unix_p.h:171
timeval & normalizedTimeval(timeval &t)
Definition: qcore_unix_p.h:104
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
Definition: qglobal.h:87
static int qt_safe_dup2(int oldfd, int newfd, int flags=FD_CLOEXEC)
Definition: qcore_unix_p.h:251
static const char * data(const QByteArray &arr)
static int qt_safe_pipe(int pipefd[2], int flags=0)
Definition: qcore_unix_p.h:191
timeval operator*(const timeval &t1, int mul)
Definition: qcore_unix_p.h:140
static int qt_safe_execv(const char *path, char *const argv[])
Definition: qcore_unix_p.h:317
__int64 qint64
Definition: qglobal.h:942
bool operator==(const timeval &t1, const timeval &t2)
Definition: qcore_unix_p.h:118
bool operator<(const timeval &t1, const timeval &t2)
Definition: qcore_unix_p.h:116
int fcntl(int, int,...)
#define QT_OPEN
Definition: qcore_unix_p.h:186
#define Q_CORE_EXPORT
Definition: qglobal.h:1449
int sigaction(int, const struct sigaction *, struct sigaction *)
QFactoryLoader * l
timeval & operator+=(timeval &t1, const timeval &t2)
Definition: qcore_unix_p.h:120
unsigned short * array
Definition: qcore_unix_p.h:357
static qint64 qt_safe_write_nosignal(int fd, const void *data, qint64 len)
Definition: qcore_unix_p.h:291
#define QT_WRITE
Definition: qcore_unix_p.h:289
timeval qt_gettime()
static pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
Definition: qcore_unix_p.h:333
static qint64 qt_safe_write(int fd, const void *data, qint64 len)
Definition: qcore_unix_p.h:282
static qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
Definition: qcore_unix_p.h:273
int errno
static int qt_safe_dup(int oldfd, int atleast=0, int flags=FD_CLOEXEC)
Definition: qcore_unix_p.h:227
#define QT_CLOSE
Definition: qcore_unix_p.h:304
timeval operator+(const timeval &t1, const timeval &t2)
Definition: qcore_unix_p.h:126