Hi,
I'm experimenting with Unix sockets, and I have a problem when client interrupts connection (with Ctrl-C for example).
Server accepts connections and each client is treated in forked process (talk() in the code). On each client's request server responds, and that works until client closes the connection (with close()). Server then knows that client finished because talk() returned and prints message Client quitted. But, if I interrupt the client execution with Ctrl-C, server sometimes (not always, but often) does not return from talk(), i.e. it does not know that client interrupted the connection! Why is that?
If I put usleep(0) after each client's request, then the communication between client and server is slower, but this problem does not occur! Does it mean that client is too fast for the server?
Also, this problem does not happen with Internet sockets. Am I doing something wrong with Unix sockets?
Thanks!

server:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>


void talk(int client_fd)
{
	char text[100];
	int status;

	while (1)
	{
		memset(text, 0, 100);
		status = recv(client_fd, text, 100, 0);
		if (!status)// client closed the connection (Ctrl+C for example)
			break;
		text[status] = '\0';
		printf("Received: %s\n", text);
		send(client_fd, text, strlen(text), 0);
	}
}


void sigchld_handler(int s)
{
    while(waitpid(-1, NULL, WNOHANG) > 0)
		;
}


int main()
{
	int server_fd;
	struct sockaddr_un server_addr;
	struct sigaction sa;

	server_fd = socket(PF_LOCAL, SOCK_STREAM, 0);
	server_addr.sun_family = AF_LOCAL;
	strcpy(server_addr.sun_path, "my.sck");
	bind(server_fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
	listen(server_fd, 5);
	
// kill zombie child process

	sa.sa_handler = sigchld_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;
	sigaction(SIGCHLD, &sa, NULL);
	
	while (1)
	{
		struct sockaddr_un client_addr;
		socklen_t addr_len;
		int client_fd;
		
		client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addr_len);
		if (!fork())// talk with client in child process
		{
			talk(client_fd);
			close(client_fd);
			printf("Client quitted.\n");
			break;
		}
		else
			printf("Server waits...\n");
	}
	close(server_fd);

	return 0;
}
and client:
Code:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>


int main(int argc, char* const argv[])
{
	int server_fd;
	struct sockaddr_un server_addr;
	char message[100];

	server_fd = socket(PF_LOCAL, SOCK_STREAM, 0);
	server_addr.sun_family = AF_LOCAL;
	strcpy(server_addr.sun_path, "my.sck");
	connect(server_fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));

	int i = 1;
	while (i++ < 50000)
	{
		sprintf(message, "%d", i);
		send(server_fd, message, strlen(message), 0);
		int status = recv(server_fd, message, 100, 0);
		message[status] = '\0';
		printf("Response: %s\n", message);
		/* usleep(0); */
	}
	close(server_fd);

	return 0;
}