Home » U++ Library support » U++ Core » SIGPIPE problem
SIGPIPE problem [message #57108] |
Wed, 26 May 2021 05:19  |
zsolt
Messages: 702 Registered: December 2005 Location: Budapest, Hungary
|
Contributor |
|
|
I'm writing an HTTP App server currently and I'm using some libraries, such as libpq.
My problem is, that some of the libraries are switching SIGPIPE signal handler on and off, and I have no control over that.
So when a client disconnects while my server is sending the HTTP response, sometimes it gets a SIGPIPE and my app stops at that point in debugger.
I'm running tons of unit tests so this is not very convenient, as some tests are doing this.
I fixed this by changing the flags argument of send() from 0 to MSG_NOSIGNAL in TcpSocket::RawSend() method.
Do you have any better idea?
int TcpSocket::RawSend(const void *buf, int amount)
{
+#ifdef PLATFORM_POSIX
+ int res = send(socket, (const char *)buf, amount, MSG_NOSIGNAL);
+#else
int res = send(socket, (const char *)buf, amount, 0);
+#endif
if(res < 0 && WouldBlock())
res = 0;
else
if(res == 0 || res < 0)
SetSockError("send");
return res;
}
|
|
|
Re: SIGPIPE problem [message #57120 is a reply to message #57108] |
Thu, 27 May 2021 09:14   |
 |
mirek
Messages: 14257 Registered: November 2005
|
Ultimate Member |
|
|
zsolt wrote on Wed, 26 May 2021 05:19I'm writing an HTTP App server currently and I'm using some libraries, such as libpq.
My problem is, that some of the libraries are switching SIGPIPE signal handler on and off, and I have no control over that.
So when a client disconnects while my server is sending the HTTP response, sometimes it gets a SIGPIPE and my app stops at that point in debugger.
I'm running tons of unit tests so this is not very convenient, as some tests are doing this.
I fixed this by changing the flags argument of send() from 0 to MSG_NOSIGNAL in TcpSocket::RawSend() method.
Do you have any better idea?
int TcpSocket::RawSend(const void *buf, int amount)
{
+#ifdef PLATFORM_POSIX
+ int res = send(socket, (const char *)buf, amount, MSG_NOSIGNAL);
+#else
int res = send(socket, (const char *)buf, amount, 0);
+#endif
if(res < 0 && WouldBlock())
res = 0;
else
if(res == 0 || res < 0)
SetSockError("send");
return res;
}
Sounds good, applied, thank you.
Mirek
|
|
|
|
Re: SIGPIPE problem [message #57132 is a reply to message #57120] |
Fri, 28 May 2021 20:41   |
Novo
Messages: 1430 Registered: December 2006
|
Ultimate Contributor |
|
|
mirek wrote on Thu, 27 May 2021 03:14
Sounds good, applied, thank you.
Mirek
MacOS 10.15: ./umk uppsrc ide CLANG -bus
/Users/ssg/worker0/m-upp/build/uppsrc/Core/Socket.cpp:565:52: error: use of undeclared identifier 'MSG_NOSIGNAL'
int res = send(socket, (const char *)buf, amount, MSG_NOSIGNAL);
^
1 error generated.
Regards,
Novo
|
|
|
Re: SIGPIPE problem [message #57139 is a reply to message #57132] |
Mon, 31 May 2021 09:44   |
 |
mirek
Messages: 14257 Registered: November 2005
|
Ultimate Member |
|
|
Ok, needs to be PLATFORM_LINUX instead... (commited).
Mirek
EDIT: "That said, question for zsolt: What about using signal(SIGPIPE, SIG_IGN) instead?" - already answered in the first post...
[Updated on: Mon, 31 May 2021 09:45] Report message to a moderator
|
|
|
|
|
|
Re: SIGPIPE problem [message #57144 is a reply to message #57143] |
Mon, 31 May 2021 17:05   |
zsolt
Messages: 702 Registered: December 2005 Location: Budapest, Hungary
|
Contributor |
|
|
Is this OK?
@@ -557,16 +557,22 @@ bool TcpSocket::WouldBlock()
}
return c == SOCKERR(EWOULDBLOCK);
#endif
}
int TcpSocket::RawSend(const void *buf, int amount)
{
-#ifdef PLATFORM_POSIX
- int res = send(socket, (const char *)buf, amount, MSG_NOSIGNAL);
+#ifdef MSG_NOSIGNAL
+#define UPP_NOSIGPIPE_OPTION MSG_NOSIGNAL
+#endif
+#ifdef SO_NOSIGPIPE
+#define UPP_NOSIGPIPE_OPTION SO_NOSIGPIPE
+# endif
+#ifdef UPP_NOSIGPIPE_OPTION
+ int res = send(socket, (const char *)buf, amount, UPP_NOSIGPIPE_OPTION);
#else
int res = send(socket, (const char *)buf, amount, 0);
#endif
if(res < 0 && WouldBlock())
res = 0;
else
if(res == 0 || res < 0)
|
|
|
|
|
Re: SIGPIPE problem [message #57147 is a reply to message #57146] |
Mon, 31 May 2021 17:18   |
Novo
Messages: 1430 Registered: December 2006
|
Ultimate Contributor |
|
|
I checked against the latest revision.
Everything compiles fine now, including FreeBSD 12.
Regards,
Novo
|
|
|
|
Re: SIGPIPE problem [message #57152 is a reply to message #57148] |
Tue, 01 June 2021 09:19   |
 |
mirek
Messages: 14257 Registered: November 2005
|
Ultimate Member |
|
|
Yeah, great, getting complicated pretty fast... 
Oblivion wrote on Mon, 31 May 2021 17:23Hello zsolt,
It looks nice but I'm afraid that won't work. SO_NOSIGPIPE should be set using the setsockopt() function, preferably at socket initialization.
E.g.
#ifdef SO_NOSIGPIPE
const int val = 1;
setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val));
#endif
Best regards,
Oblivion
Is it guaranteed to be #define though?
But perhaps even if it is not, it would be worth it...
Mirek
|
|
|
Re: SIGPIPE problem [message #57154 is a reply to message #57152] |
Tue, 01 June 2021 13:15  |
Oblivion
Messages: 1206 Registered: August 2007
|
Senior Contributor |
|
|
Well, the SIGPIPE issue is a relic network/socket programmers have to deal with, dating back to the implementation of TCP sockets in unix in early 80s.
AFAIK, there is no perfect solution. While the posix manual seems to define MSG_NOSIGNAL from some point on, it is not adopted by every camp yet.
Another workaround seems to be this, which I didn't know either:
Quote:
The most general solution, for when you are not in full control of the program's signal handling and want to write data to an actual pipe or use write(2) on a socket, is to first mask the signal for the current thread with pthread_sigmask(3), write the data, drain any pending signal with sigtimedwait(2) and a zero timeout, and then finally unmask SIGPIPE. This technique is described in more detail here. Note that some systems such as OpenBSD do not have sigtimedwait(2) in which case you need to use sigpending(2) to check for pending signals and then call the blocking sigwait(2).
Read the full blog, here:
https://www.doof.me.uk/2020/09/23/sigpipe-and-how-to-ignore- it/
Workaround (explained):
https://web.archive.org/web/20200126153413/http://www.microh owto.info:80/howto/ignore_sigpipe_without_affecting_other_th reads_in_a_process.html
Best regards,
Oblivion
Github page: https://github.com/ismail-yilmaz
upp-components: https://github.com/ismail-yilmaz/upp-components
Bobcat the terminal emulator: https://github.com/ismail-yilmaz/Bobcat
[Updated on: Tue, 01 June 2021 13:23] Report message to a moderator
|
|
|
Goto Forum:
Current Time: Fri May 09 16:00:51 CEST 2025
Total time taken to generate the page: 0.03362 seconds
|