At 05:10 PM 1/25/02 +0100, Corinna Vinschen wrote:
>On Fri, Jan 25, 2002 at 10:39:30AM -0500, Pierre A. Humblet wrote:

<snip, long example>
>> Any thoughts?
>
>Not immediately.  Two questions:
>
<snip, already answered>

>- Could you patch Cygwin fhandler_socket.cc, fhandler_socket::close()
>  and rip out the whole linger stuff so that only the naked closesocket()
>  call remains and see if that changes the behaviour?
>
Corinna,

No difference (on Win98 and Me. I will try NT on Monday).

I can now duplicate exactly what's happening in the application I am porting.
A key element is that it disconnects itself from the controlling terminal
by closing fd 0, 1 & 2 and forking. Weird things happen afterwards:
1) For every re-exec (triggered by -HUP), ps -W and the Windows task manager
   show an extra copy of the program.
   [without the disconnect from the controlling terminal, only one process
appears]
2) If a tcp call was received and a child was forked, then after the next
re-exec
   netstat -a shows an extra LISTEN on port 999. It never goes away. This
happens
   even if the -HUP is given long after (I tried up to 5 minutes) the child
   terminates. Eventually incoming calls are not answered.
   [without the disconnect from the controlling terminal, an extra LISTEN
appears 
    only if the -HUP was given while the child is running, and it
disappears when 
    the child exits]
I have no idea where to start debugging that. I am attaching the demo program.
It is used as shown in the previous message, and also using ps -W. 

Ntsec good news: I think I have identified and solved the problem of
having an incorrect UID, and also of setting the DACL in the token security
descriptor. I will test on Monday and let you know.

Pierre
/**********************************************
 *
 This demo program exposes a bug where there
 are to listen on the same tcp port.
 New connections may or may not be accepted

**********************************************/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include <netinet/in.h>
#include <unistd.h>

enum {FALSE, TRUE};

/*************************************************
*             SIGHUP Handler                     *
*************************************************/
static int sighup_seen;

static void
sighup_handler(int sig)
{
sig = sig;    /* Keep picky compilers happy */
sighup_seen = TRUE;
signal(SIGHUP, sighup_handler);
}

main(int argc, char * argv[])
{
  int on = 1, sockfd, newsockfd, lcount, peer_size;
  int status, cpid, pid;
  struct sockaddr_in addr, peer;
  fd_set select_listen;
  FILE *fd;
  char msg[100];
//  struct linger linger;
//  linger.l_onoff = 1;
//  linger.l_linger = 0;

#if 1
  close(0);
  close(1);
  close(2);
  pid = 0;
  if (getppid() != 1) {   /* not a re-exec */
          unlink("demo.log"); /* old log */
          pid = fork();
          if (pid > 0) exit(EXIT_SUCCESS);   /* in parent process, just exit */
//        setsid();
  }
#endif
  fd = fopen("demo.log", "a");
  if (pid < 0) {
          fprintf(fd, "Fork: %s\n", strerror(errno));
          exit(1);
  }

  /************************************************
   *
   Open a socket and listen on port 999

  ************************************************/

  sockfd = socket(AF_INET, SOCK_STREAM, 0);
  if (sockfd < 0)
        fprintf(fd, "socket: %s\n", strerror(errno));

  if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
        fprintf(fd, "setsockopt: %s\n", strerror(errno));
  if (setsockopt(sockfd, SOL_SOCKET, TCP_NODELAY, &on, sizeof(on)) < 0)
          fprintf(fd, "setsockopt: %s\n", strerror(errno));
//  if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (const char *)&linger, sizeof 
linger) < 0)
//        fprintf(fd, "setsockopt: %s\n", strerror(errno));
  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(999);
  addr.sin_addr.s_addr = INADDR_ANY;
  if (bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
        fprintf(fd, "bind: %s\n", strerror(errno));

  if (listen(sockfd, 10) < 0)
        fprintf(fd, "listen: %d %s\n", errno, strerror(errno));

  sighup_seen = FALSE;
  signal(SIGHUP, sighup_handler);
  pid = getpid();

  /************************************************
   *
   Now wait for a call or sighup, causing a re-exec
   After a re-exec following a call, there are two
   listen on port 999 (netstat -a)
   Incoming calls may or may not work.

  ************************************************/

  while(1) {
        FD_ZERO(&select_listen);
        FD_SET(sockfd, &select_listen);
        fprintf(fd, "looping pid %d\n", pid);
        lcount = select(sockfd + 1, &select_listen, NULL, NULL, NULL);
        if (lcount == 1) {
          peer_size = sizeof(peer);
          newsockfd = accept(sockfd, (struct sockaddr *) &peer, &peer_size);
          if (newsockfd < 0) {
                fprintf(fd, "accept: %s\n", strerror(errno));
          }
          else {
                fprintf(fd, "Got a call\n");
                fflush(fd);
                if ((cpid = fork()) == 0) {
                  signal(SIGHUP, SIG_IGN);
                  close(sockfd);
                  sprintf(msg, "Hello world. Type kill -HUP %d\n", pid);
                  write(newsockfd, msg, strlen(msg));
                  /* In this demo we sleep, in reality the child is working */
                  sleep(60);
                  fprintf(fd, "Child exiting\n");
                  fclose(fd);
                  close(newsockfd);
                  exit(0);
                }
                else if (cpid > 0) {
                  fprintf(fd, "Process %d started\n", cpid);
                  close(newsockfd);
                }
                else fprintf(fd, "Fork %s\n", strerror(errno));
          }
        }
        else if (sighup_seen == TRUE) {
          fprintf(fd, "Sighup seen. Execing\n");
          fclose(fd);
          close(sockfd);
          signal(SIGHUP, SIG_IGN);
          execv(argv[0], argv);
        }
        else fprintf(fd, "Select error %s\n", strerror(errno));
        fflush(fd);
  }
}

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Reply via email to