1 #ifndef _BABELTRACE_COMPAT_SEND_H
2 #define _BABELTRACE_COMPAT_SEND_H
5 * babeltrace/compat/send.h
7 * Copyright (C) 2015 Michael Jeanson <mjeanson@efficios.com>
8 * 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * This wrapper is used on platforms that have no way of ignoring SIGPIPE
36 # define MSG_NOSIGNAL SO_NOSIGPIPE
40 #if defined(MSG_NOSIGNAL)
42 ssize_t
bt_send_nosigpipe(int fd
, const void *buffer
, size_t size
)
44 return send(fd
, buffer
, size
, MSG_NOSIGNAL
);
51 ssize_t
bt_send_nosigpipe(int fd
, const void *buffer
, size_t size
)
55 sigset_t sigpipe_set
, pending_set
, old_set
;
56 int sigpipe_was_pending
;
59 * Discard the SIGPIPE from send(), not disturbing any SIGPIPE
60 * that might be already pending. If a bogus SIGPIPE is sent to
61 * the entire process concurrently by a malicious user, it may
62 * be simply discarded.
64 if (sigemptyset(&pending_set
)) {
68 * sigpending returns the mask of signals that are _both_
69 * blocked for the thread _and_ pending for either the thread or
72 if (sigpending(&pending_set
)) {
75 sigpipe_was_pending
= sigismember(&pending_set
, SIGPIPE
);
77 * If sigpipe was pending, it means it was already blocked, so
78 * no need to block it.
80 if (!sigpipe_was_pending
) {
81 if (sigemptyset(&sigpipe_set
)) {
84 if (sigaddset(&sigpipe_set
, SIGPIPE
)) {
87 if (pthread_sigmask(SIG_BLOCK
, &sigpipe_set
, &old_set
)) {
92 /* Send and save errno. */
93 sent
= send(fd
, buffer
, size
, 0);
96 if (sent
== -1 && errno
== EPIPE
&& !sigpipe_was_pending
) {
97 struct timespec timeout
= { 0, 0 };
101 ret
= sigtimedwait(&sigpipe_set
, NULL
,
103 } while (ret
== -1 && errno
== EINTR
);
105 if (!sigpipe_was_pending
) {
106 if (pthread_sigmask(SIG_SETMASK
, &old_set
, NULL
)) {
110 /* Restore send() errno */
117 #endif /* _BABELTRACE_COMPAT_SEND_H */
This page took 0.032759 seconds and 4 git commands to generate.