0

I have a C socket client program where one thread is for receiving data and another for sending. If the server shuts down then the sender gets EPIPE. If I reconnect the same socket then it can receive data but the sender still gets EPIPE.

How to fix this?

Update: Actually sender seems to send data as I see number of byte sent. But errno is still set to broken pipe. Before I only checked errno. Shouldn't it be changed to successful?

nomem
  • 1,568
  • 4
  • 17
  • 33
  • I didn't know you *could* reconnect a socket. Are you sure it works properly? – user253751 Nov 30 '15 at 03:37
  • By reconnect I mean destroy and connect again. – nomem Nov 30 '15 at 03:39
  • 2
    Are you sure the sender is using the new socket? – user253751 Nov 30 '15 at 03:57
  • Do I understand you correctly that you have a single bi-directional socket file descriptor and you have one thread using it to write to the server and another using the same file descriptor to read from the server? When you reconnect to the server, do you ever get an indication that you can write anything? Presumably the server was restarted after it shut down. How do you know that the receiver can still receive? Was it, perchance, reading residual data that the server had sent before it shut down that had not been read yet? – Jonathan Leffler Nov 30 '15 at 03:59
  • 'Tis going to be difficult to debug this because it's likely the MCVE ([How to create a Minimal, Complete, and Verifiable Example?](http://stackoverflow.com/help/mcve)) involves two programs — a minimal server and a minimal client, plus some scripting to start, stop and restart the server. Do you know why the server shut down? Did it shut down completely, or just shut down the one connection? – Jonathan Leffler Nov 30 '15 at 04:00
  • @immibis yes I am sure sender is using the new socket as it is declared globally. – nomem Nov 30 '15 at 04:25
  • @JonathanLeffler I only send a small packet as heartbeat repeatedly and yes I know it is not reading any residual data because I am receiving a lot of data for a long time after reconnecting which are not residual. I am testing the problem for both normal and abnormal shutdown. I am shutting down the server. – nomem Nov 30 '15 at 04:26

1 Answers1

1

If I reconnect the same socket then it can receive data but the sender still gets EPIPE.

That can only mean that the sender is still sending via the old socket; also that you haven't closed the old socket.

sender seems to send data as I see number of byte sent. But errno is still set to broken pipe. Before I only checked errno. Shouldn't it be changed to successful?

No. It is only valid to check errno when an immediately prior system call has returned -1. Example:

int rc = send(...);
if (rc < 0)
{
    if (errno == EWOULDBLOCK) // or EAGAIN *and* we are in non-blocking mode
    {
        // queue the write and return to the select() loop
    }
    else
    {
        perror("send"); // for example
    }
}
else
{
    // write succeeded ...
}
user207421
  • 305,947
  • 44
  • 307
  • 483
  • I am sure that the socket is closed. – nomem Nov 30 '15 at 05:47
  • You may well be sure, but the symptoms don't agree with you. Examine your assumptions. The only other, very improbable, possibility is that the peer has shutdown his socket for input. – user207421 Nov 30 '15 at 06:20
  • Sorry my question has changed actually. I can send data but errno is still set to EPIPE. I think send call sets the errno to previous error code. As you can see "errno is never set to zero by any system call or library function" in [link](http://man7.org/linux/man-pages/man3/errno.3.html) . Thanks by the way. – nomem Nov 30 '15 at 07:08
  • 2
    That suggests that you're checking `errno` even when a system call *hasn't* returned -1, which isn't valid. Checking `errno` is only valid when an immediately prior system call has returned -1. – user207421 Nov 30 '15 at 08:33