I cannot understand why this application dies on send
. Here is the code for the server:
#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.
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.
When you call send()
on an already closed connection, the operating system may issue SIGPIPE
to your process. Usually the default handler for SIGPIPE
is to kill your process.
In order to prevent this from occurring, you can either ignore the signal (e.g., with signal(SIGPIPE, SIG_IGN)
or sigignore(SIGPIPE)
), or you 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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With