From: jik@athena.mit.edu (Jonathan I. Kamens)
Newsgroups: comp.unix.programmer
Subject: Re: Using SO_KEEPALIVE to detect the death of a client???
Date: 7 Apr 92 05:03:12 GMT
Organization: Massachusetts Institute of Technology

In article <1992Apr6.132012@hoggar.imag.fr> jean@hoggar.imag.fr (Jean Chouanard) writes:

   Newsgroups: comp.unix.wizards

   I'm working on a client//server model and my server have to detect the death
   of his client. I'm working on SunOS 4.1.1 / Sparc 2.

   I know that's a FAQ but I how do that working!

Um, what?

   I saw that you cant set option SO_KEEPALIVE on the communication socket to 
   enables the periodic transmission of messages on this socket,

1) I assume you mean "can set."

2) SO_KEEPALIVE is the wrong way to detect the closure of a socket
connection.  Either use a select loop (the socket will show ready for
read when it has been closed, and a read on it will return 0 bytes
read, indicating EOF), or use fcntl to set yourself as the owner of
the socket and turn on asynchronous I/O on the socket, which will
cause your process to get a SIGIO when there is input available on the
socket; when the socket has closed, you will get SIGIO, and once
again, read on the socket will return 0 bytes.

   that 
   what I've done, but nothing else change! I was expecting a signal SIGPIPE but 
   No signal!

First of all: I believe (although I'm not certain) that SIGPIPE is
only going to be sent to your process if you try to write to the
socket after it has been closed, just as SIGPIPE is documented in the
sigvec(2) man page.  Yes, the documentation about this is bad.  I'm
not 100% certain about this.

Second: As far as I can tell from a basic probing of the kernel
sources, using SO_KEEPALIVE causes a socket to stay alive for *two
hours* after the connection starts having trouble.  Therefore, even if
your code were write, your server wouldn't get any signals for *two
hours*.

   Here is my code for the client and the server. 

No, actually, here are two fragments of code that quite simply do not
compile, making it quite difficult for us to test and help you with
your problem.  I had to make these changes to your sample programs
just to get them to compile:

*** Server.c	Tue Apr  7 00:27:40 1992
--- server.c	Tue Apr  7 00:32:25 1992
***************
*** 1,3 ****
--- 1,8 ----
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <signal.h>
+      
  recup_sig_pipe()
  {
    printf ("I've got a signal!!!\n");
***************
*** 13,19 ****
    int i,k,ver;
    int res;
    static int one = 1;
!   
  
    s = socket(AF_INET,SOCK_STREAM,0);
    bzero(&sin, sizeof (sin));
--- 18,24 ----
    int i,k,ver;
    int res;
    static int one = 1;
!   int g1;
  
    s = socket(AF_INET,SOCK_STREAM,0);
    bzero(&sin, sizeof (sin));
***************
*** 26,41 ****
    res = bind(s, (struct sockaddr *) &sin, sizeof(struct sockaddr_in));
    if (res != 0){
      perror("bind :");
!     exit;
    }
    if (listen(s,1) < 0){
      perror("listen :");
!     exit;
    }
    g1 = accept(s,&client,&lg);
    if (g1 < 0){
      perror("accept :");
!     exit;
    }
    if (setsockopt(g1, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
  sizeof(one)) < 0)	{
--- 31,46 ----
    res = bind(s, (struct sockaddr *) &sin, sizeof(struct sockaddr_in));
    if (res != 0){
      perror("bind :");
!     exit(1);
    }
    if (listen(s,1) < 0){
      perror("listen :");
!     exit(1);
    }
    g1 = accept(s,&client,&lg);
    if (g1 < 0){
      perror("accept :");
!     exit(1);
    }
    if (setsockopt(g1, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
  sizeof(one)) < 0)	{
*** Client.c	Tue Apr  7 00:27:57 1992
--- client.c	Tue Apr  7 00:36:15 1992
***************
*** 1,3 ****
--- 1,11 ----
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <stdio.h>
+ #include <netdb.h>
+ 
+ #define SERVER_HOST	"pit-manager"
+ 
  main()
  {
  
***************
*** 22,28 ****
        close(s);
        return(NULL);
      }
!     if ((hpl = gethostbyname("hoggar")) == NULL){
        perror("gethostbyname :");
        close(s);
        return(NULL);
--- 30,36 ----
        close(s);
        return(NULL);
      }
!     if ((hpl = gethostbyname(SERVER_HOST)) == NULL){
        perror("gethostbyname :");
        close(s);
        return(NULL);

Furthermore, I note that the " :" in all of your calls to perror are
unnecessary, since perror inserts the colon and the space after it
automatically.

I also had to modify the client to use my host name instead of yours,
and then to exit at the bottom (since the client is *never* going to
get a SIGPIPE, in any case, if the client never exits).

Even after doing all of that, running the server and the client still
didn't cause the server to get a SIGPIPE, probably because it didn't
try to write to the socket.  I modified it to write to the socket
before looping, but I didn't feel like waiting around for two hours to
see if that causes a SIGPIPE to be generated, especially since this is
almost certainly the wrong way for you to achieve what you're trying
to achieve.  If you really want to know, I suggest you try it.

There are some morals that I find it necessary to point out after
reading your posting: (1) I realize that you are not a native English
speaker, but at least some of the errors you made in your posting
could have been eliminated by proof-reading it before posting.  Please
try to do that in the future.  (2) If you want people to help you,
please include WORKING, COMPILEABLE sample code in your posting.

-- 
Jonathan Kamens						jik@MIT.Edu
MIT Information Systems/Athena		    Moderator, news.answers
    (Send correspondence related to the news.answers newsgroup
	{and ONLY correspondence related to the newsgroup}
		 to news-answers-request@MIT.Edu.)