Download as pdf or txt
Download as pdf or txt
You are on page 1of 5

sockets - Server dies on `send` if client was closed wi... https://stackoverflow.com/questions/17332646/server-...

Server dies on `send` if client was closed with Ctrl+c


Asked 10 years, 7 months ago Modified 9 years, 9 months ago Viewed 9k times

1 of 5 1/30/24, 21:35
sockets - Server dies on `send` if client was closed wi... https://stackoverflow.com/questions/17332646/server-...

I cannot understand why this application dies on send . Here is the code for the server:

5 #include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <stdlib.h>
#include <errno.h>

#define UNIX_PATH_MAX 108


#define SPATH "./sock"

int main() {
int sfd, rv = 100, newfd;
char b[100];
char ok[3] = "ok\0";
struct sockaddr_un sa;

sfd = socket(AF_UNIX, SOCK_STREAM, 0);

strncpy(sa.sun_path, SPATH, UNIX_PATH_MAX);


sa.sun_family = AF_UNIX;

if (bind(sfd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {


perror("bind");
exit(EXIT_FAILURE);
}

if (listen(sfd, SOMAXCONN) == -1) {


perror("listen");
exit(EXIT_FAILURE);
}

if ((newfd = accept(sfd, NULL, NULL)) == -1) {


perror("accept");
exit(EXIT_FAILURE);
}

while (rv != -1 && rv != 0) {


rv = recv(newfd, b, 100, 0);

printf("%s\n", b);

sleep(3);

printf("Send reply\n");
send(newfd, ok, 3, 0);
printf("Sent reply\n");
}

printf("END\n");
}

Unfortunately, if the client was forcefully closed using Ctrl+C as soon as it has sent the
message, server will print (as last line):

before send

And then it dies without doing anything else. I tried to check errno or whatever else
(including the call to send in an if statement), but it seems that it's send itself to cause the
server to die. I've tryed with a write but it's the same.

2 of 5 1/30/24, 21:35
sockets - Server dies on `send` if client was closed wi... https://stackoverflow.com/questions/17332646/server-...

server to die. I've tryed with a write but it's the same.

I checked it's return code with bash, and it exits with return code 141, which I was unable
to understand what it means.

If you want to try, here is the client code:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>

#define UNIX_PATH_MAX 108


#define SPATH "./sock"

int main() {
int sfd, rv;
char b[100];
char ok[3];
struct sockaddr_un sa;

sfd = socket(AF_UNIX, SOCK_STREAM, 0);

strncpy(sa.sun_path, SPATH, UNIX_PATH_MAX);


sa.sun_family = AF_UNIX;

connect(sfd, (struct sockaddr*)&sa, sizeof(sa));

while (scanf("%s", b)) {


send(sfd, b, 100, 0);

recv(sfd, ok, 3, 0);

printf("%s\n", ok);
}

printf("END\n");
}

Just compile both, run both and then kill the client with Ctrl+C just after the message has
been sent.

c sockets send

Share Follow asked Jun 27, 2013 at 0:27


Zagorax
11.6k 8 44 58

But isn't that what is expected? After all the client to where the server was writing the data is no
available anymore. – MeTitus Jun 27, 2013 at 0:33

In the server, right after the while, why you didn't check the return value of recv() ??, also before
using printf, you must nul terminate your newly receive string, for instance, b[rev] = 0 – yeyo Jun
27, 2013 at 0:36

1 Nobody is going to 'just compile both, run both, and then kill the client'. You're expected to post the

3 of 5 1/30/24, 21:35
sockets - Server dies on `send` if client was closed wi... https://stackoverflow.com/questions/17332646/server-...

Nobody is going to 'just compile both, run both, and then kill the client'. You're expected to post the
error messages, stack traces, etc here. This is not a free 2nd level help desk and you are not
reporting a software bug in some vendor's code. -1Sorted
– user207421 Jun 27, 2013 at 0:46
2 Answers by: Highest score (default)
1 When a program's exit status is > 128, it means it was killed due to a signal status-128 . If you
look up the Unix signal list, you'll see that 13 is SIGPIPE . – Barmar Jun 27, 2013 at 0:50
When you call send() on an already closed connection, the operating system may issue
@EJP,to
1SIGPIPE your process.
probably nobody had Usually theit,default
compiled handler
but some peoplefor
have read theiswhole
SIGPIPE to killquestion
your process.
and not
just the last line. I've posted the error code I get and they found a solution without even try to run
16 the code. Thank you
In order to prevent thisforfrom
youroccurring,
lesson on how
youtocan
ask either
question on Stackoverflow,
ignore but unfortunately
the signal (e.g., with
that was not my doubt.
signal(SIGPIPE, SIG_IGN) Cheers. – Zagorax Jun 27, 2013
or sigignore(SIGPIPE) at you
), or 7:44 can pass the MSG_NOSIGNAL

option to send() :

int send_result = send(newfd, ok, 3, MSG_NOSIGNAL);


if (send_result >= 0) {
/* okay, but check if all your data got sent! */
if (send_result < 3) /* ...do something */;
} else {
switch (errno) {
/* ... */
case EPIPE:
/* sending on a closed connection... */
}
}

Now, instead of issuing SIGPIPE , the send() call will fail, and errno will be set to EPIPE .

Share Follow edited Apr 21, 2014 at 20:45 answered Jun 27, 2013 at 0:33
jxh
69.6k 8 111 195

There is no need to use errno, man page explicity says: ""The return value will be 0 when the peer
has performed an orderly shutdown."" so, this MIGHT not even be a portable solution, testing for
EPIPE. – yeyo Jun 27, 2013 at 0:46

1 We check errno if the result is less than 0 , indicating an error. The 0 return for orderly
shutdown is with recv() . I haven't used a system where the EPIPE check was wrong for
send() (Solaris, Linux, BSD, Winsock). – jxh Jun 27, 2013 at 1:01

Richard Stevens - Unix network programming Third Edition, Chapter 5, section 5.3 TCP Echo
Server. The author suggest testing for 0 and not EPIPE, in fact I was not able to find any evidence
pointing the use of EPIPE. But of course, your answer seems to be correct. – yeyo Jun 27, 2013 at
1:17

but again I see no evidence of using EPIPE insted of checking for 0. Did you see Figure 5.14
tcpcliserv/str_cli11.c line 10, Richard is testing for 0. if (Readline(sockfd, recvline,
MAXLINE) == 0) . – yeyo Jun 27, 2013 at 1:29

Thank you very much. MSG_NOSIGNAL solved the problem. Now I can catch the error correctly.
– Zagorax Jun 27, 2013 at 7:47

4 of 5 1/30/24, 21:35
sockets - Server dies on `send` if client was closed wi... https://stackoverflow.com/questions/17332646/server-...

in the server side, check if the client closed the connexion:

0 rv = recv(newfd, b, 100, 0);


if(rv<=0) {
if(!rv) {
fprintf(stderr, "conn. closed.");
} else {
perror("recv");
}
exit(EXIT_FAILURE);
}

Share Follow edited Jun 27, 2013 at 1:07 answered Jun 27, 2013 at 0:39
yeyo
2,980 2 30 40

!rv isn't correct. You must check for rv == 0 to detect EOS, and -1 to detect an error.
– user207421 Jun 27, 2013 at 0:45

@EJP wait!, 0 evaluate to false, anything else evaluate to TRUE, if rv==0, then !rv will evaluate to
TRUE and the fprintf function will be executed. Asterisk CodingStyle explicitly suggest using
!variable instead of variable==0. man your -1 is so incorrect. – yeyo Jun 27, 2013 at 0:50

1 This will not prevent the observed crash from occurring if the server is sending when the client has
already been killed. – jxh Jun 27, 2013 at 1:07

@Kira It's a trick, and a confusing one, as this discussion shows. The return value is documented
as -1, 0, or a positive integer, and that is what you should test. There is no such recommendation in
the coding style you cite. – user207421 Jun 27, 2013 at 1:54

@EJP I'm so sorry for the bad citation; human mistake, I meant, Mozilla Coding Style, section:
C/C++ practices. Here: developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style very
easy to check. "...Use (x) or (!x) instead..." – yeyo Jun 27, 2013 at 2:19

5 of 5 1/30/24, 21:35

You might also like