I SIGPIPE-out when I try to send data to a socket that's been closed
on the other side. I understand that I have to check with select() if
my socket is still active but i don't quite understand how I can do
this.
My code:
if (log_sock>-1) {
sndlen=strlen(res);
syslog(LOG_ERR, "_run_logger(): got strlen(res):%d, log_sock:
%d",sndlen, log_sock);
reclen=send(log_sock, res, sndlen, 0);
syslog(LOG_ERR, "_run_logger(): sent \'%s\"",res);
How do I need to use the select() statement before the if to verify if
my socket is still open?
Thank you!
Ron
Basically, your socket is open until you close it.
If the other end has close()ed the connection then:
-> your write() will return -1 with errno set properly (EPIPE).
-> your read() will return 0 on EOF (or -1 with errno set properly)
Select() and poll() will return a socket as readable or writable
if it is safe for you to call read() or write() without blocking.
So you will in any case need to set a signal handler for SIGPIPE to SIGIGN
to handle the EPIPE case (the default handler is ABRT)
(there are more details, causing you to need setting the sockets to
non-blockable, but DS will hanle that case ;-)
HTH,
AvK
So, should I be using write() instead of send? send() apparently ends
up in a SIGPIPE exception...
> Select() and poll() will return a socket as readable or writable
> if it is safe for you to call read() or write() without blocking.
exactly, I should be able to read with select if my socket is
writable, right?
> So you will in any case need to set a signal handler for SIGPIPE to SIGIGN
> to handle the EPIPE case (the default handler is ABRT)
set a signal handler? With setjmp()? Hm...
Okay,
I tried it like this
FD_ZERO(&sendset);
FD_SET(log_sock, &sendset);
recv_tv.tv_sec = 0;
recv_tv.tv_usec = 10000;//10ms
select(log_sock+1, NULL, &sendset, NULL, &send_tv);
if (log_sock>-1 && FD_ISSET(log_sock, &sendset)) {
sndlen=strlen(res);
syslog(LOG_ERR, "_run_logger(): got strlen(res):%d, log_sock:
%d",sndlen, log_sock);
reclen=send(log_sock, res, sndlen, 0);
But it doesn't seem to work. I always get the "got strlen" message the
last and nothing past it and my debugger tells me:
Program received signal SIGPIPE, Broken pipe.
Program terminated with signal SIGPIPE, Broken pipe.
The program no longer exists.
(gdb)
:(( What am I doing wrong there? :o
Thanks!
Ron
> On Jan 7, 2:56 pm, Moi <r...@invalid.address.org> wrote:
>> On Thu, 07 Jan 2010 14:21:44 -0800, cerr wrote:
>> > Hi There,
>>
>> > I SIGPIPE-out when I try to send data to a socket that's been closed
>> > on the other side. I understand that I have to check with select() if
>> > my socket is still active but i don't quite understand how I can do
>> > this. My code:
>>
>> > if (log_sock>-1) {
>> > sndlen=strlen(res);
>> > syslog(LOG_ERR, "_run_logger(): got strlen(res):%d, log_sock:
>> > %d",sndlen, log_sock);
>> > reclen=send(log_sock, res, sndlen, 0); syslog(LOG_ERR,
>> > "_run_logger(): sent \'%s\"",res);
>>
>> > How do I need to use the select() statement before the if to verify
>> > if my socket is still open?
>>
>> Basically, your socket is open until you close it. If the other end has
>> close()ed the connection then:
>>
>> -> your write() will return -1 with errno set properly (EPIPE). -> your
>> read() will return 0 on EOF (or -1 with errno set properly)
>
> So, should I be using write() instead of send? send() apparently ends up
> in a SIGPIPE exception...
You could, but there is no difference in return and errno.
[in your case, you don't _need_ sendto(), write() would be good enough]
>> Select() and poll() will return a socket as readable or writable if it
>> is safe for you to call read() or write() without blocking.
>
> exactly, I should be able to read with select if my socket is writable,
> right?
Learn how to read.
You can call read() or write() , and they won't block.
(but instead return immediately with 0 or -1)
>> So you will in any case need to set a signal handler for SIGPIPE to
>> SIGIGN to handle the EPIPE case (the default handler is ABRT)
>
> set a signal handler? With setjmp()? Hm...
No. signal() or sigaction()
man 2 signal
HTH,
AvK
You can't.
The problem is that TCP doesn't provide a way for the receiver to tell
you that it doesn't want any more data. The only way to find out is to
send data; if it didn't want any more, it responds with a RST packet.
This causes you to get a SIGPIPE signal. If you're ignoring this
signal, you'll get an EPIPE error on the *next* operation on the socket.
You should design your application protocol so that the other end tells
you when it's closing the connection. And in case the other end
terminates abnormally, you should just establish a handler for SIGPIPE.
--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
> I SIGPIPE-out when I try to send data to a socket that's been closed
> on the other side.
What do you want to happen in this case?
> I understand that I have to check with select() if
> my socket is still active but i don't quite understand how I can do
> this.
That's wrong on so many levels, but the most obvious is this: suppose
there was some function that could tell you if the socket was okay or
not. How would that help you? Just because it was okay when you asked
doesn't mean it will still be okay when you try to use it.
> How do I need to use the select() statement before the if to verify if
> my socket is still open?
That would be really silly. That would mean two system calls where one
would do 99.9999% of the time. Ignore SIGPIPE or handle it, depending
on what you want to do.
DS
> Select() and poll() will return a socket as readable or writable
> if it is safe for you to call read() or write() without blocking.
It's always safe to call 'read' or 'write' without blocking.
> So you will in any case need to set a signal handler for SIGPIPE to SIGIGN
> to handle the EPIPE case (the default handler is ABRT)
Exactly.
> (there are more details, causing you to need setting the sockets to
> non-blockable, but DS will hanle that case ;-)
If you don't want to block, you have to set the sockets non-blocking.
If you want to block if an operation cannot be completed (or fail)
immediately, then don't set them non-blocking. We can't tell which the
OP wants.
DS
>> (there are more details, causing you to need setting the sockets to
>> non-blockable, О©╫but DS will hanle that case ;-)
DS> If you don't want to block, you have to set the sockets non-blocking.
This could have side effects of appearing of non-blocking mode for
other descriptor (possibly in other process), as soon as F_SETFL flags
affect "ofile", not descriptor. When this is important, I prefer to
rely on select/poll notifications.
I would like to see non-blocking mark on _operation_, not _object_.
This is already true for send*/recv* in some OSes as Linux, but can be
easily spread to other kinds of objects. There is no essential reasons
except historic legacy to allow send() and recv() only for sockets.
--netch--
Okay, I understand.
> >> So you will in any case need to set a signal handler for SIGPIPE to
> >> SIGIGN to handle the EPIPE case (the default handler is ABRT)
>
> > set a signal handler? With setjmp()? Hm...
>
> No. signal() or sigaction()
> man 2 signal
Yes,
signal (SIGPIPE,SIG_IGN);
this has done the trick, thanks!
Yep,
signal (SIGPIPE,SIG_IGN);
did the trick for me. I just read how many bytes have been sent and
proceed upon that the way i want....