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/