Revert "SIGPIPE suppression for platforms without SO_NOSIGPIPE or MSG_NOSIGNAL"

This reverts commit 131deb3976. It added
code that shouldn't have entered the project repo.

Conflicts:
	src/msg/async/AsyncConnection.cc
	src/msg/async/AsyncConnection.h
	src/msg/simple/Pipe.cc
	src/msg/simple/Pipe.h

Signed-off-by: Greg Farnum <gfarnum@redhat.com>
This commit is contained in:
Greg Farnum 2017-10-03 15:06:25 -07:00
parent e25d30c612
commit 21bdb73093
7 changed files with 15 additions and 174 deletions

View File

@ -145,8 +145,3 @@ Files: src/include/timegm.h
Copyright (C) Copyright Howard Hinnant
Copyright (C) Copyright 2010-2011 Vicente J. Botet Escriba
License: Boost Software License, Version 1.0
Files: src/msg/async/AsyncConnection.cc, src/msg/simple/Pipe.cc (sigpipe suppression)
Copyright (C) 2010 Tomash Brechko. All rights reserved.
License: GPL3

View File

@ -11,4 +11,16 @@
# define MSG_MORE 0
#endif
/*
* On BSD SO_NOSIGPIPE can be set via setsockopt to block SIGPIPE.
*/
#ifndef MSG_NOSIGNAL
# define MSG_NOSIGNAL 0
# ifdef SO_NOSIGPIPE
# define CEPH_USE_SO_NOSIGPIPE
# else
# error "Cannot block SIGPIPE!"
# endif
#endif
#endif

View File

@ -19,7 +19,6 @@
#include <atomic>
#include <pthread.h>
#include <signal.h>
#include <climits>
#include <list>
#include <mutex>

View File

@ -40,11 +40,6 @@ class PosixConnectedSocketImpl final : public ConnectedSocketImpl {
int _fd;
entity_addr_t sa;
bool connected;
#if !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE)
sigset_t sigpipe_mask;
bool sigpipe_pending;
bool sigpipe_unblock;
#endif
public:
explicit PosixConnectedSocketImpl(NetHandler &h, const entity_addr_t &sa, int f, bool connected)
@ -76,83 +71,14 @@ class PosixConnectedSocketImpl final : public ConnectedSocketImpl {
return r;
}
/*
SIGPIPE suppression - for platforms without SO_NOSIGPIPE or MSG_NOSIGNAL
http://krokisplace.blogspot.in/2010/02/suppressing-sigpipe-in-library.html
http://www.microhowto.info/howto/ignore_sigpipe_without_affecting_other_threads_in_a_process.html
*/
static void suppress_sigpipe()
{
#if !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE)
/*
We want to ignore possible SIGPIPE that we can generate on write.
SIGPIPE is delivered *synchronously* and *only* to the thread
doing the write. So if it is reported as already pending (which
means the thread blocks it), then we do nothing: if we generate
SIGPIPE, it will be merged with the pending one (there's no
queuing), and that suits us well. If it is not pending, we block
it in this thread (and we avoid changing signal action, because it
is per-process).
*/
sigset_t pending;
sigemptyset(&pending);
sigpending(&pending);
sigpipe_pending = sigismember(&pending, SIGPIPE);
if (!sigpipe_pending) {
sigset_t blocked;
sigemptyset(&blocked);
pthread_sigmask(SIG_BLOCK, &sigpipe_mask, &blocked);
/* Maybe is was blocked already? */
sigpipe_unblock = ! sigismember(&blocked, SIGPIPE);
}
#endif /* !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE) */
}
static void restore_sigpipe()
{
#if !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE)
/*
If SIGPIPE was pending already we do nothing. Otherwise, if it
become pending (i.e., we generated it), then we sigwait() it (thus
clearing pending status). Then we unblock SIGPIPE, but only if it
were us who blocked it.
*/
if (!sigpipe_pending) {
sigset_t pending;
sigemptyset(&pending);
sigpending(&pending);
if (sigismember(&pending, SIGPIPE)) {
/*
Protect ourselves from a situation when SIGPIPE was sent
by the user to the whole process, and was delivered to
other thread before we had a chance to wait for it.
*/
static const struct timespec nowait = { 0, 0 };
TEMP_FAILURE_RETRY(sigtimedwait(&sigpipe_mask, NULL, &nowait));
}
if (sigpipe_unblock)
pthread_sigmask(SIG_UNBLOCK, &sigpipe_mask, NULL);
}
#endif /* !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE) */
}
// return the sent length
// < 0 means error occured
static ssize_t do_sendmsg(int fd, struct msghdr &msg, unsigned len, bool more)
{
suppress_sigpipe();
size_t sent = 0;
while (1) {
ssize_t r;
#if defined(MSG_NOSIGNAL)
r = ::sendmsg(fd, &msg, MSG_NOSIGNAL | (more ? MSG_MORE : 0));
#else
r = ::sendmsg(fd, &msg, (more ? MSG_MORE : 0));
#endif /* defined(MSG_NOSIGNAL) */
if (r < 0) {
if (errno == EINTR) {
continue;
@ -178,7 +104,6 @@ class PosixConnectedSocketImpl final : public ConnectedSocketImpl {
}
}
}
restore_sigpipe();
return (ssize_t)sent;
}

View File

@ -119,7 +119,7 @@ int NetHandler::set_socket_options(int sd, bool nodelay, int size)
}
// block ESIGPIPE
#ifdef SO_NOSIGPIPE
#ifdef CEPH_USE_SO_NOSIGPIPE
int val = 1;
r = ::setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&val, sizeof(val));
if (r) {

View File

@ -911,7 +911,7 @@ void Pipe::set_socket_options()
}
// block ESIGPIPE
#if defined(SO_NOSIGPIPE)
#ifdef CEPH_USE_SO_NOSIGPIPE
int val = 1;
int r = ::setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&val, sizeof(val));
if (r) {
@ -2261,91 +2261,20 @@ int Pipe::read_message(Message **pm, AuthSessionHandler* auth_handler)
return ret;
}
/*
SIGPIPE suppression - for platforms without SO_NOSIGPIPE or MSG_NOSIGNAL
http://krokisplace.blogspot.in/2010/02/suppressing-sigpipe-in-library.html
http://www.microhowto.info/howto/ignore_sigpipe_without_affecting_other_threads_in_a_process.html
*/
void Pipe::suppress_sigpipe()
{
#if !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE)
/*
We want to ignore possible SIGPIPE that we can generate on write.
SIGPIPE is delivered *synchronously* and *only* to the thread
doing the write. So if it is reported as already pending (which
means the thread blocks it), then we do nothing: if we generate
SIGPIPE, it will be merged with the pending one (there's no
queuing), and that suits us well. If it is not pending, we block
it in this thread (and we avoid changing signal action, because it
is per-process).
*/
sigset_t pending;
sigemptyset(&pending);
sigpending(&pending);
sigpipe_pending = sigismember(&pending, SIGPIPE);
if (!sigpipe_pending) {
sigset_t blocked;
sigemptyset(&blocked);
pthread_sigmask(SIG_BLOCK, &sigpipe_mask, &blocked);
/* Maybe is was blocked already? */
sigpipe_unblock = ! sigismember(&blocked, SIGPIPE);
}
#endif /* !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE) */
}
void Pipe::restore_sigpipe()
{
#if !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE)
/*
If SIGPIPE was pending already we do nothing. Otherwise, if it
become pending (i.e., we generated it), then we sigwait() it (thus
clearing pending status). Then we unblock SIGPIPE, but only if it
were us who blocked it.
*/
if (!sigpipe_pending) {
sigset_t pending;
sigemptyset(&pending);
sigpending(&pending);
if (sigismember(&pending, SIGPIPE)) {
/*
Protect ourselves from a situation when SIGPIPE was sent
by the user to the whole process, and was delivered to
other thread before we had a chance to wait for it.
*/
static const struct timespec nowait = { 0, 0 };
TEMP_FAILURE_RETRY(sigtimedwait(&sigpipe_mask, NULL, &nowait));
}
if (sigpipe_unblock)
pthread_sigmask(SIG_UNBLOCK, &sigpipe_mask, NULL);
}
#endif /* !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE) */
}
int Pipe::do_sendmsg(struct msghdr *msg, unsigned len, bool more)
{
suppress_sigpipe();
while (len > 0) {
int r;
#if defined(MSG_NOSIGNAL)
r = ::sendmsg(sd, msg, MSG_NOSIGNAL | (more ? MSG_MORE : 0));
#else
r = ::sendmsg(sd, msg, (more ? MSG_MORE : 0));
#endif
if (r == 0)
ldout(msgr->cct,10) << "do_sendmsg hmm do_sendmsg got r==0!" << dendl;
if (r < 0) {
r = -errno;
ldout(msgr->cct,1) << "do_sendmsg error " << cpp_strerror(r) << dendl;
restore_sigpipe();
return r;
}
if (state == STATE_CLOSED) {
ldout(msgr->cct,10) << "do_sendmsg oh look, state == CLOSED, giving up" << dendl;
restore_sigpipe();
return -EINTR; // close enough
}
@ -2370,7 +2299,6 @@ int Pipe::do_sendmsg(struct msghdr *msg, unsigned len, bool more)
}
}
}
restore_sigpipe();
return 0;
}
@ -2737,15 +2665,8 @@ int Pipe::tcp_write(const char *buf, unsigned len)
//lgeneric_dout(cct, DBL) << "tcp_write writing " << len << dendl;
assert(len > 0);
suppress_sigpipe();
while (len > 0) {
int did;
#if defined(MSG_NOSIGNAL)
did = ::send( sd, buf, len, MSG_NOSIGNAL );
#else
did = ::send( sd, buf, len, 0);
#endif
int did = ::send( sd, buf, len, MSG_NOSIGNAL );
if (did < 0) {
//lgeneric_dout(cct, 1) << "tcp_write error did = " << did << " " << cpp_strerror(errno) << dendl;
//lgeneric_derr(cct, 1) << "tcp_write error did = " << did << " " << cpp_strerror(errno) << dendl;
@ -2755,7 +2676,5 @@ int Pipe::tcp_write(const char *buf, unsigned len)
buf += did;
//lgeneric_dout(cct, DBL) << "tcp_write did " << did << ", " << len << " left" << dendl;
}
restore_sigpipe();
return 0;
}

View File

@ -115,11 +115,6 @@ static const int SM_IOV_MAX = (IOV_MAX >= 1024 ? IOV_MAX / 4 : IOV_MAX);
private:
int sd;
struct iovec msgvec[SM_IOV_MAX];
#if !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE)
sigset_t sigpipe_mask;
bool sigpipe_pending;
bool sigpipe_unblock;
#endif
public:
int port;
@ -188,10 +183,6 @@ static const int SM_IOV_MAX = (IOV_MAX >= 1024 ? IOV_MAX / 4 : IOV_MAX);
int write_keepalive();
int write_keepalive2(char tag, const utime_t &t);
void suppress_sigpipe();
void restore_sigpipe();
void fault(bool reader=false);
void was_session_reset();