mirror of
https://salsa.debian.org/ha-team/libqb
synced 2026-08-11 09:56:06 +00:00
Solaris based operating systems don't define MSG_NOSIGNAL and SO_NOSIGPIPE.
They return SIGPIPE when send is used with a closed socket. A SIGPIPE handler must be used or SIGPIPE should be set ignored with SIG_IGN. In this case send returns -1 instead of a SIGPIPE. The setting to ignore SIGPIPE is global and should be used only where it is absolutely necessary. Signed-off-by: Angus Salkeld <asalkeld@redhat.com>
This commit is contained in:
parent
bcba4a2983
commit
79059bcae3
58
lib/ipc_us.c
58
lib/ipc_us.c
@ -74,14 +74,36 @@ struct ipc_auth_ugp {
|
||||
static int32_t qb_ipcs_us_connection_acceptor(int fd, int revent, void *data);
|
||||
static int32_t qb_ipc_us_fc_get(struct qb_ipc_one_way *one_way);
|
||||
|
||||
#ifdef SO_NOSIGPIPE
|
||||
static void
|
||||
socket_nosigpipe(int32_t s)
|
||||
{
|
||||
#ifdef SO_NOSIGPIPE
|
||||
int32_t on = 1;
|
||||
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on));
|
||||
#endif /* SO_NOSIGPIPE */
|
||||
}
|
||||
|
||||
|
||||
enum qb_sigpipe_ctl {
|
||||
QB_SIGPIPE_IGNORE,
|
||||
QB_SIGPIPE_DEFAULT,
|
||||
};
|
||||
|
||||
static void sigpipe_ctl(enum qb_sigpipe_ctl ctl)
|
||||
{
|
||||
#if !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE)
|
||||
struct sigaction act;
|
||||
struct sigaction oact;
|
||||
|
||||
act.sa_handler = SIG_IGN;
|
||||
|
||||
if (ctl == QB_SIGPIPE_IGNORE) {
|
||||
sigaction(SIGPIPE, &act, &oact);
|
||||
} else {
|
||||
sigaction(SIGPIPE, &oact, NULL);
|
||||
}
|
||||
#endif /* !MSG_NOSIGNAL && !defined(SO_NOSIGPIPE) */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
#define MSG_NOSIGNAL 0
|
||||
@ -94,6 +116,8 @@ qb_ipc_us_send(struct qb_ipc_one_way *one_way, const void *msg, size_t len)
|
||||
int32_t processed = 0;
|
||||
char *rbuf = (char *)msg;
|
||||
|
||||
sigpipe_ctl(QB_SIGPIPE_IGNORE);
|
||||
|
||||
retry_send:
|
||||
result = send(one_way->u.us.sock,
|
||||
&rbuf[processed],
|
||||
@ -104,6 +128,7 @@ retry_send:
|
||||
if (errno == EAGAIN && processed > 0) {
|
||||
goto retry_send;
|
||||
} else {
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
@ -112,6 +137,9 @@ retry_send:
|
||||
if (processed != len) {
|
||||
goto retry_send;
|
||||
}
|
||||
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
|
||||
if (one_way->type == QB_IPC_SOCKET) {
|
||||
struct ipc_us_control *ctl = NULL;
|
||||
ctl = (struct ipc_us_control *)one_way->u.us.shared_data;
|
||||
@ -132,6 +160,8 @@ qb_ipc_us_sendv(struct qb_ipc_one_way *one_way, const struct iovec *iov,
|
||||
int32_t iov_p = 0;
|
||||
char *rbuf = (char *)iov[iov_p].iov_base;
|
||||
|
||||
sigpipe_ctl(QB_SIGPIPE_IGNORE);
|
||||
|
||||
retry_send:
|
||||
result = send(one_way->u.us.sock,
|
||||
&rbuf[processed],
|
||||
@ -143,6 +173,7 @@ retry_send:
|
||||
(processed > 0 || iov_p > 0)) {
|
||||
goto retry_send;
|
||||
} else {
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
@ -159,6 +190,9 @@ retry_send:
|
||||
} else {
|
||||
goto retry_send;
|
||||
}
|
||||
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
|
||||
if (one_way->type == QB_IPC_SOCKET) {
|
||||
struct ipc_us_control *ctl;
|
||||
ctl = (struct ipc_us_control *)one_way->u.us.shared_data;
|
||||
@ -175,6 +209,8 @@ qb_ipc_us_recv_msghdr(int32_t s, struct msghdr *hdr, char *msg, size_t len)
|
||||
int32_t result;
|
||||
int32_t processed = 0;
|
||||
|
||||
sigpipe_ctl(QB_SIGPIPE_IGNORE);
|
||||
|
||||
retry_recv:
|
||||
hdr->msg_iov->iov_base = &msg[processed];
|
||||
hdr->msg_iov->iov_len = len - processed;
|
||||
@ -184,9 +220,11 @@ retry_recv:
|
||||
goto retry_recv;
|
||||
}
|
||||
if (result == -1) {
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
return -errno;
|
||||
}
|
||||
if (result == 0) {
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
qb_util_log(LOG_DEBUG,
|
||||
"recv(fd %d) got 0 bytes assuming ENOTCONN", s);
|
||||
return -ENOTCONN;
|
||||
@ -196,6 +234,7 @@ retry_recv:
|
||||
if (processed != len) {
|
||||
goto retry_recv;
|
||||
}
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
assert(processed == len);
|
||||
|
||||
return processed;
|
||||
@ -257,6 +296,8 @@ qb_ipc_us_recv(struct qb_ipc_one_way * one_way,
|
||||
int32_t to_recv = len;
|
||||
char *data = msg;
|
||||
|
||||
sigpipe_ctl(QB_SIGPIPE_IGNORE);
|
||||
|
||||
retry_recv:
|
||||
result = recv(one_way->u.us.sock, &data[processed], to_recv,
|
||||
MSG_NOSIGNAL | MSG_WAITALL);
|
||||
@ -266,16 +307,19 @@ retry_recv:
|
||||
(processed > 0 || timeout == -1)) {
|
||||
goto retry_recv;
|
||||
} else if (errno == ECONNRESET || errno == EPIPE) {
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
qb_util_perror(LOG_DEBUG,
|
||||
"recv(fd %d) converting to ENOTCONN",
|
||||
one_way->u.us.sock);
|
||||
return -ENOTCONN;
|
||||
} else {
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
qb_util_log(LOG_DEBUG,
|
||||
"recv(fd %d) got 0 bytes assuming ENOTCONN",
|
||||
one_way->u.us.sock);
|
||||
@ -286,6 +330,7 @@ retry_recv:
|
||||
if (processed != len) {
|
||||
goto retry_recv;
|
||||
}
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
if (one_way->type == QB_IPC_SOCKET) {
|
||||
struct ipc_us_control *ctl = NULL;
|
||||
ctl = (struct ipc_us_control *)one_way->u.us.shared_data;
|
||||
@ -310,6 +355,8 @@ qb_ipc_us_recv_at_most(struct qb_ipc_one_way * one_way,
|
||||
struct ipc_us_control *ctl = NULL;
|
||||
struct qb_ipc_request_header *hdr = NULL;
|
||||
|
||||
sigpipe_ctl(QB_SIGPIPE_IGNORE);
|
||||
|
||||
retry_recv:
|
||||
result = recv(one_way->u.us.sock, &data[processed], to_recv,
|
||||
MSG_NOSIGNAL | MSG_WAITALL);
|
||||
@ -318,9 +365,11 @@ retry_recv:
|
||||
(processed > 0 || timeout == -1)) {
|
||||
goto retry_recv;
|
||||
} else {
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
return -errno;
|
||||
}
|
||||
} else if (result == 0) {
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
qb_util_log(LOG_DEBUG,
|
||||
"recv(fd %d) got 0 bytes assuming ENOTCONN",
|
||||
one_way->u.us.sock);
|
||||
@ -339,6 +388,7 @@ retry_recv:
|
||||
if (to_recv > 0) {
|
||||
goto retry_recv;
|
||||
}
|
||||
sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
||||
ctl = (struct ipc_us_control *)one_way->u.us.shared_data;
|
||||
if (ctl) {
|
||||
(void)qb_atomic_int_dec_and_test(&ctl->sent);
|
||||
@ -358,9 +408,9 @@ qb_ipcc_us_sock_connect(const char *socket_name, int32_t * sock_pt)
|
||||
if (request_fd == -1) {
|
||||
return -errno;
|
||||
}
|
||||
#ifdef SO_NOSIGPIPE
|
||||
|
||||
socket_nosigpipe(request_fd);
|
||||
#endif /* SO_NOSIGPIPE */
|
||||
|
||||
res = qb_sys_fd_nonblock_cloexec_set(request_fd);
|
||||
if (res < 0) {
|
||||
goto error_connect;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user