From: Greg Farnum Date: Tue, 3 Oct 2017 22:06:25 +0000 (-0700) Subject: Revert "SIGPIPE suppression for platforms without SO_NOSIGPIPE or MSG_NOSIGNAL" X-Git-Tag: v12.2.2~169^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=0251cfcd17111334d3f13dc1e9d52a9aa9302354;p=ceph.git Revert "SIGPIPE suppression for platforms without SO_NOSIGPIPE or MSG_NOSIGNAL" This reverts commit 131deb39769c1187c334ee84f552d3be01f1751b. 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 (cherry picked from commit 21bdb730932196a48407be0effab8813a78c4b1b) --- diff --git a/COPYING b/COPYING index b7371e4f9c0..a87427936a5 100644 --- a/COPYING +++ b/COPYING @@ -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 - diff --git a/src/include/sock_compat.h b/src/include/sock_compat.h index 56eb92bd6e3..5faacc343ed 100644 --- a/src/include/sock_compat.h +++ b/src/include/sock_compat.h @@ -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 diff --git a/src/msg/async/AsyncConnection.h b/src/msg/async/AsyncConnection.h index 005b7c13ab2..ab2ff2c4ab0 100644 --- a/src/msg/async/AsyncConnection.h +++ b/src/msg/async/AsyncConnection.h @@ -19,7 +19,6 @@ #include #include -#include #include #include #include diff --git a/src/msg/async/PosixStack.cc b/src/msg/async/PosixStack.cc index d0e6b5af083..1bcffb469fc 100644 --- a/src/msg/async/PosixStack.cc +++ b/src/msg/async/PosixStack.cc @@ -41,11 +41,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) @@ -77,83 +72,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; @@ -179,7 +105,6 @@ class PosixConnectedSocketImpl final : public ConnectedSocketImpl { } } } - restore_sigpipe(); return (ssize_t)sent; } diff --git a/src/msg/async/net_handler.cc b/src/msg/async/net_handler.cc index 19adb2c83f2..99ca1f32d92 100644 --- a/src/msg/async/net_handler.cc +++ b/src/msg/async/net_handler.cc @@ -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) { diff --git a/src/msg/simple/Pipe.cc b/src/msg/simple/Pipe.cc index 4a7ab9acab7..368efdb82a5 100644 --- a/src/msg/simple/Pipe.cc +++ b/src/msg/simple/Pipe.cc @@ -907,7 +907,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) { @@ -2257,91 +2257,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 } @@ -2366,7 +2295,6 @@ int Pipe::do_sendmsg(struct msghdr *msg, unsigned len, bool more) } } } - restore_sigpipe(); return 0; } @@ -2733,15 +2661,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; @@ -2751,7 +2672,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; } diff --git a/src/msg/simple/Pipe.h b/src/msg/simple/Pipe.h index 9dd00d1b48f..d8d2a8e0831 100644 --- a/src/msg/simple/Pipe.h +++ b/src/msg/simple/Pipe.h @@ -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();