QtBase  v6.3.1
qcore_unix_p.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Copyright (C) 2016 Intel Corporation.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #ifndef QCORE_UNIX_P_H
42 #define QCORE_UNIX_P_H
43 
44 //
45 // W A R N I N G
46 // -------------
47 //
48 // This file is not part of the Qt API. It exists for the convenience
49 // of Qt code on Unix. This header file may change from version to
50 // version without notice, or even be removed.
51 //
52 // We mean it.
53 //
54 
55 #include "qplatformdefs.h"
56 #include <QtCore/private/qglobal_p.h>
57 #include "qatomic.h"
58 #include "qbytearray.h"
59 
60 #ifndef Q_OS_UNIX
61 # error "qcore_unix_p.h included on a non-Unix system"
62 #endif
63 
64 #include <string.h>
65 #include <sys/types.h>
66 #include <sys/stat.h>
67 #include <unistd.h>
68 
69 #if !defined (Q_OS_VXWORKS)
70 # if !defined(Q_OS_HPUX) || defined(__ia64)
71 # include <sys/select.h>
72 # endif
73 # include <sys/time.h>
74 #else
75 # include <selectLib.h>
76 #endif
77 
78 #include <sys/wait.h>
79 #include <errno.h>
80 #include <fcntl.h>
81 
82 #if !defined(QT_POSIX_IPC) && !defined(QT_NO_SHAREDMEMORY) && !defined(Q_OS_ANDROID)
83 # include <sys/ipc.h>
84 #endif
85 
86 #if defined(Q_OS_VXWORKS)
87 # include <ioLib.h>
88 #endif
89 
90 #ifdef QT_NO_NATIVE_POLL
91 # include "qpoll_p.h"
92 #else
93 # include <poll.h>
94 #endif
95 
96 struct sockaddr;
97 
98 #define EINTR_LOOP(var, cmd) \
99  do { \
100  var = cmd; \
101  } while (var == -1 && errno == EINTR)
102 
104 
106 
107 // Internal operator functions for timespecs
108 constexpr inline timespec &normalizedTimespec(timespec &t)
109 {
110  while (t.tv_nsec >= 1000000000) {
111  ++t.tv_sec;
112  t.tv_nsec -= 1000000000;
113  }
114  while (t.tv_nsec < 0) {
115  --t.tv_sec;
116  t.tv_nsec += 1000000000;
117  }
118  return t;
119 }
120 constexpr inline bool operator<(const timespec &t1, const timespec &t2)
121 { return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec); }
122 constexpr inline bool operator==(const timespec &t1, const timespec &t2)
123 { return t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec; }
124 constexpr inline bool operator!=(const timespec &t1, const timespec &t2)
125 { return !(t1 == t2); }
126 constexpr inline timespec &operator+=(timespec &t1, const timespec &t2)
127 {
128  t1.tv_sec += t2.tv_sec;
129  t1.tv_nsec += t2.tv_nsec;
130  return normalizedTimespec(t1);
131 }
132 constexpr inline timespec operator+(const timespec &t1, const timespec &t2)
133 {
134  timespec tmp = {};
135  tmp.tv_sec = t1.tv_sec + t2.tv_sec;
136  tmp.tv_nsec = t1.tv_nsec + t2.tv_nsec;
137  return normalizedTimespec(tmp);
138 }
139 constexpr inline timespec operator-(const timespec &t1, const timespec &t2)
140 {
141  timespec tmp = {};
142  tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1);
143  tmp.tv_nsec = t1.tv_nsec - (t2.tv_nsec + 1000000000);
144  return normalizedTimespec(tmp);
145 }
146 constexpr inline timespec operator*(const timespec &t1, int mul)
147 {
148  timespec tmp = {};
149  tmp.tv_sec = t1.tv_sec * mul;
150  tmp.tv_nsec = t1.tv_nsec * mul;
151  return normalizedTimespec(tmp);
152 }
153 inline timeval timespecToTimeval(const timespec &ts)
154 {
155  timeval tv;
156  tv.tv_sec = ts.tv_sec;
157  tv.tv_usec = ts.tv_nsec / 1000;
158  return tv;
159 }
160 
161 
162 inline void qt_ignore_sigpipe()
163 {
164  // Set to ignore SIGPIPE once only.
166  if (!atom.loadRelaxed()) {
167  // More than one thread could turn off SIGPIPE at the same time
168  // But that's acceptable because they all would be doing the same
169  // action
170  struct sigaction noaction;
171  memset(&noaction, 0, sizeof(noaction));
172  noaction.sa_handler = SIG_IGN;
173  ::sigaction(SIGPIPE, &noaction, nullptr);
174  atom.storeRelaxed(1);
175  }
176 }
177 
178 #if defined(Q_PROCESSOR_X86_32) && defined(__GLIBC__)
179 # if !__GLIBC_PREREQ(2, 22)
180 Q_CORE_EXPORT int qt_open64(const char *pathname, int flags, mode_t);
181 # undef QT_OPEN
182 # define QT_OPEN qt_open64
183 # endif
184 #endif
185 
186 // don't call QT_OPEN or ::open
187 // call qt_safe_open
188 static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777)
189 {
190 #ifdef O_CLOEXEC
191  flags |= O_CLOEXEC;
192 #endif
193  int fd;
194  EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode));
195 
196 #ifndef O_CLOEXEC
197  if (fd != -1)
198  ::fcntl(fd, F_SETFD, FD_CLOEXEC);
199 #endif
200 
201  return fd;
202 }
203 #undef QT_OPEN
204 #define QT_OPEN qt_safe_open
205 
206 #ifndef Q_OS_VXWORKS // no POSIX pipes in VxWorks
207 // don't call ::pipe
208 // call qt_safe_pipe
209 static inline int qt_safe_pipe(int pipefd[2], int flags = 0)
210 {
211  Q_ASSERT((flags & ~O_NONBLOCK) == 0);
212 
213 #ifdef QT_THREADSAFE_CLOEXEC
214  // use pipe2
215  flags |= O_CLOEXEC;
216  return ::pipe2(pipefd, flags); // pipe2 is documented not to return EINTR
217 #else
218  int ret = ::pipe(pipefd);
219  if (ret == -1)
220  return -1;
221 
222  ::fcntl(pipefd[0], F_SETFD, FD_CLOEXEC);
223  ::fcntl(pipefd[1], F_SETFD, FD_CLOEXEC);
224 
225  // set non-block too?
226  if (flags & O_NONBLOCK) {
227  ::fcntl(pipefd[0], F_SETFL, ::fcntl(pipefd[0], F_GETFL) | O_NONBLOCK);
228  ::fcntl(pipefd[1], F_SETFL, ::fcntl(pipefd[1], F_GETFL) | O_NONBLOCK);
229  }
230 
231  return 0;
232 #endif
233 }
234 
235 #endif // Q_OS_VXWORKS
236 
237 // don't call dup or fcntl(F_DUPFD)
238 static inline int qt_safe_dup(int oldfd, int atleast = 0, int flags = FD_CLOEXEC)
239 {
240  Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
241 
242 #ifdef F_DUPFD_CLOEXEC
243  int cmd = F_DUPFD;
244  if (flags & FD_CLOEXEC)
245  cmd = F_DUPFD_CLOEXEC;
246  return ::fcntl(oldfd, cmd, atleast);
247 #else
248  // use F_DUPFD
249  int ret = ::fcntl(oldfd, F_DUPFD, atleast);
250 
251  if (flags && ret != -1)
252  ::fcntl(ret, F_SETFD, flags);
253  return ret;
254 #endif
255 }
256 
257 // don't call dup2
258 // call qt_safe_dup2
259 static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC)
260 {
261  Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
262 
263  int ret;
264 #ifdef QT_THREADSAFE_CLOEXEC
265  // use dup3
266  EINTR_LOOP(ret, ::dup3(oldfd, newfd, flags ? O_CLOEXEC : 0));
267  return ret;
268 #else
269  EINTR_LOOP(ret, ::dup2(oldfd, newfd));
270  if (ret == -1)
271  return -1;
272 
273  if (flags)
274  ::fcntl(newfd, F_SETFD, flags);
275  return 0;
276 #endif
277 }
278 
279 static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
280 {
281  qint64 ret = 0;
282  EINTR_LOOP(ret, QT_READ(fd, data, maxlen));
283  return ret;
284 }
285 #undef QT_READ
286 #define QT_READ qt_safe_read
287 
288 static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
289 {
290  qint64 ret = 0;
292  return ret;
293 }
294 #undef QT_WRITE
295 #define QT_WRITE qt_safe_write
296 
297 static inline qint64 qt_safe_write_nosignal(int fd, const void *data, qint64 len)
298 {
300  return qt_safe_write(fd, data, len);
301 }
302 
303 static inline int qt_safe_close(int fd)
304 {
305  int ret;
307  return ret;
308 }
309 #undef QT_CLOSE
310 #define QT_CLOSE qt_safe_close
311 
312 // - VxWorks & iOS/tvOS/watchOS don't have processes
313 #if QT_CONFIG(process)
314 static inline int qt_safe_execve(const char *filename, char *const argv[],
315  char *const envp[])
316 {
317  int ret;
318  EINTR_LOOP(ret, ::execve(filename, argv, envp));
319  return ret;
320 }
321 
322 static inline int qt_safe_execv(const char *path, char *const argv[])
323 {
324  int ret;
325  EINTR_LOOP(ret, ::execv(path, argv));
326  return ret;
327 }
328 
329 static inline int qt_safe_execvp(const char *file, char *const argv[])
330 {
331  int ret;
332  EINTR_LOOP(ret, ::execvp(file, argv));
333  return ret;
334 }
335 
336 static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
337 {
338  int ret;
339  EINTR_LOOP(ret, ::waitpid(pid, status, options));
340  return ret;
341 }
342 #endif // QT_CONFIG(process)
343 
344 #if !defined(_POSIX_MONOTONIC_CLOCK)
345 # define _POSIX_MONOTONIC_CLOCK -1
346 #endif
347 
348 // in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp
349 timespec qt_gettime() noexcept;
350 void qt_nanosleep(timespec amount);
352 
353 /* non-static */
355 {
356 #ifdef Q_OS_LINUX
357 # ifdef QT_LINUX_ALWAYS_HAVE_PROCFS
358  return true;
359 # else
360  static const bool present = (access("/proc/version", F_OK) == 0);
361  return present;
362 # endif
363 #else
364  return false;
365 #endif
366 }
367 
368 Q_CORE_EXPORT int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts);
369 
370 static inline int qt_poll_msecs(struct pollfd *fds, nfds_t nfds, int timeout)
371 {
372  timespec ts, *pts = nullptr;
373 
374  if (timeout >= 0) {
375  ts.tv_sec = timeout / 1000;
376  ts.tv_nsec = (timeout % 1000) * 1000 * 1000;
377  pts = &ts;
378  }
379 
380  return qt_safe_poll(fds, nfds, pts);
381 }
382 
383 static inline struct pollfd qt_make_pollfd(int fd, short events)
384 {
385  struct pollfd pfd = { fd, events, 0 };
386  return pfd;
387 }
388 
389 // according to X/OPEN we have to define semun ourselves
390 // we use prefix as on some systems sem.h will have it
391 struct semid_ds;
392 union qt_semun {
393  int val; /* value for SETVAL */
394  struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
395  unsigned short *array; /* array for GETALL, SETALL */
396 };
397 
399 
400 #endif
void storeRelaxed(T newValue) noexcept
Definition: qbasicatomic.h:91
T loadRelaxed() const noexcept
Definition: qbasicatomic.h:90
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
const QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
Definition: qbytearray.h:575
bool operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
template< typename Enum > bool operator!=(Enum lhs, QFlags< Enum > rhs)
template< typename Enum > bool operator==(Enum lhs, QFlags< Enum > rhs)
QMargins operator*(const QMargins &margins, int factor)
Definition: qmargins.h:192
QMargins operator-(const QMargins &m1, const QMargins &m2)
Definition: qmargins.h:168
auto it unsigned count const
Definition: hb-iter.hh:848
#define inline
Definition: md4c.c:45
#define Q_BASIC_ATOMIC_INITIALIZER(a)
constexpr timespec & operator+=(timespec &t1, const timespec &t2)
Definition: qcore_unix_p.h:126
Q_CORE_EXPORT int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
Definition: qcore_unix.cpp:150
QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(pollfd, Q_PRIMITIVE_TYPE)
#define QT_READ
Definition: qcore_unix_p.h:286
timeval timespecToTimeval(const timespec &ts)
Definition: qcore_unix_p.h:153
timespec qt_gettime() noexcept
#define QT_OPEN
Definition: qcore_unix_p.h:204
constexpr timespec & normalizedTimespec(timespec &t)
Definition: qcore_unix_p.h:108
bool qt_haveLinuxProcfs()
Definition: qcore_unix_p.h:354
void qt_ignore_sigpipe()
Definition: qcore_unix_p.h:162
void qt_nanosleep(timespec amount)
#define EINTR_LOOP(var, cmd)
Definition: qcore_unix_p.h:98
#define QT_CLOSE
Definition: qcore_unix_p.h:310
QByteArray qt_readlink(const char *path)
Definition: qcore_unix.cpp:59
#define QT_WRITE
Definition: qcore_unix_p.h:295
long long qint64
Definition: qglobal.h:298
GLenum mode
GLbitfield GLuint64 timeout
[4]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
[4]
GLenum access
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint64 GLenum GLint fd
GLenum GLsizei len
Definition: qopenglext.h:3292
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
GLsizei const GLchar *const * path
Definition: qopenglext.h:4283
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
@ Q_PRIMITIVE_TYPE
Definition: qtypeinfo.h:155
QFile file
[0]
QSize t2(10, 12)
struct semid_ds * buf
Definition: qcore_unix_p.h:394
unsigned short * array
Definition: qcore_unix_p.h:395
#define F_OK
int mode_t