From owner-freebsd-ports@FreeBSD.ORG Sun Mar 7 18:49:51 2004 Return-Path: Delivered-To: freebsd-ports@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 9A95C16A4CE for ; Sun, 7 Mar 2004 18:49:51 -0800 (PST) Received: from redmaple.bitnets.net (redmaple.bitnets.net [216.123.230.38]) by mx1.FreeBSD.org (Postfix) with ESMTP id 5293F43D2D for ; Sun, 7 Mar 2004 18:49:51 -0800 (PST) (envelope-from b04@interbaun.com) Received: from interbaun.com ([24.65.200.244]) by redmaple.bitnets.net (NO UCE) with ASMTP (SSL) id FFP37861; Sun, 07 Mar 2004 19:49:50 -0700 Message-ID: <404BDF4D.2070208@interbaun.com> Date: Sun, 07 Mar 2004 19:49:49 -0700 From: Gary Bajaj User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113 X-Accept-Language: en-ca, en-us, en MIME-Version: 1.0 To: Lars.Koeller@Uni-Bielefeld.de Content-Type: multipart/mixed; boundary="------------000001020500010208080609" cc: ports@FreeBSD.org Subject: FreeBSD Port: apcupsd-3.10.11 X-BeenThere: freebsd-ports@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Porting software to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 08 Mar 2004 02:49:51 -0000 This is a multi-part message in MIME format. --------------000001020500010208080609 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit apcupsd-3.10.11 rev 2 with --disable-pthreads set dumps core. The fix is to remove --disable-pthreads and apply Adam Kropelin's (modified) patch - attached. I have tested it this day and it seems to work perfectly in simulated power failure and complete shutdown tests. --------------000001020500010208080609 Content-Type: text/plain; name="patch-pthreads" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="patch-pthreads" --- ./src/apcnis.c Fri Jul 18 05:32:19 2003 +++ ./apcupsd-3.10.11-debug3/src/apcnis.c Fri Feb 6 21:19:14 2004 @@ -197,7 +197,6 @@ int newsockfd, sockfd, childpid; struct sockaddr_in cli_addr; /* client's address */ struct sockaddr_in serv_addr; /* our address */ - socklen_t clilen; int tlog; int turnon = 1; struct s_arg *arg; @@ -269,11 +268,7 @@ /* * Wait for a connection from a client process. */ - clilen = sizeof(cli_addr); - for (tlog=0; (newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen)) < 0; tlog -= 5*60 ) { - if (errno == EINTR) { - continue; - } + for (tlog=0; (newsockfd = net_accept(sockfd, &cli_addr)) < 0; tlog -= 5*60 ) { if (tlog <= 0) { tlog = 60*60; log_event(ups, LOG_ERR, "apcserver: accept error. ERR=%s", --- ./src/lib/apclibnis.c Sat Aug 3 18:49:45 2002 +++ ./apcupsd-3.10.11-debug3/src/lib/apclibnis.c Fri Feb 6 21:38:58 2004 @@ -71,12 +71,50 @@ static int read_nbytes(int fd, char *ptr, int nbytes) { - int nleft, nread; - + int nleft, nread, rc; + +#if defined HAVE_PTHREADS && (defined HAVE_OPENBSD_OS || defined HAVE_FREEBSD_OS) + fd_set fds; +#endif + nleft = nbytes; - errno = 0; + while (nleft > 0) { + do { + +#if defined HAVE_PTHREADS && (defined HAVE_OPENBSD_OS || defined HAVE_FREEBSD_OS) + /* + * Work around a bug in OpenBSD & FreeBSD userspace pthreads + * implementations. + * + * The pthreads implementation under the hood sets O_NONBLOCK + * implicitly on all fds. This setting is not visible to the user + * application but is relied upon by the pthreads library to prevent + * blocking syscalls in one thread from halting all threads in the + * process. When a process exit()s or exec()s, the implicit + * O_NONBLOCK flags are removed from all fds, EVEN THOSE IT INHERITED. + * If another process is still using the inherited fds, there will + * soon be trouble. + * + * apcupsd is bitten by this issue after fork()ing a child process to + * run apccontrol. + * + * select() is conveniently immune to the O_NONBLOCK issue so we use + * that to make sure the following read() will not block. + */ + do { + FD_ZERO(&fds); + FD_SET(fd, &fds); + rc = select(fd+1, &fds, NULL, NULL, NULL); + } while (rc == -1 && (errno == EINTR || errno == EAGAIN)); + if (rc < 0) + { + net_errno = errno; + return(-1); /* error */ + } +#endif + nread = read(fd, ptr, nleft); } while (nread == -1 && (errno == EINTR || errno == EAGAIN)); if (nread <= 0) { @@ -100,6 +138,15 @@ nleft = nbytes; while (nleft > 0) { +#if defined HAVE_PTHREADS && (defined HAVE_OPENBSD_OS || defined HAVE_FREEBSD_OS) + /* + * Work around a bug in OpenBSD & FreeBSD userspace pthreads + * implementations. Rationale is the same as described above. + * This seemingly-pointless fcntl() call causes the pthreads + * library to reapply the O_NONBLOCK flag appropriately. + */ + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)); +#endif nwritten = write(fd, ptr, nleft); if (nwritten <= 0) { net_errno = errno; @@ -225,6 +272,13 @@ return -1; } /* connect to server */ +#if defined HAVE_PTHREADS && (defined HAVE_OPENBSD_OS || defined HAVE_FREEBSD_OS) + /* + * Work around a bug in OpenBSD & FreeBSD userspace pthreads + * implementations. Rationale is the same as described above. + */ + fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL)); +#endif if (connect(sockfd, (struct sockaddr *) &tcp_serv_addr, sizeof(tcp_serv_addr)) < 0) { sprintf(net_errbuf, "tcp_open: cannot connect to server %s on port %d.\n\ ERR=%s\n", host, port, strerror(errno)); @@ -243,6 +297,50 @@ close(sockfd); } +/* + * Accept a TCP connection. + * Returns -1 on error. + * Returns file descriptor of new connection otherwise. + */ +int net_accept(int fd, struct sockaddr_in *cli_addr) +{ + socklen_t clilen = sizeof(*cli_addr); + int newfd, rc; + +#if defined HAVE_PTHREADS && (defined HAVE_OPENBSD_OS || defined HAVE_FREEBSD_OS) + fd_set fds; +#endif + + do { + +#if defined HAVE_PTHREADS && (defined HAVE_OPENBSD_OS || defined HAVE_FREEBSD_OS) + /* + * Work around a bug in OpenBSD & FreeBSD userspace pthreads + * implementations. Rationale is the same as described above. + */ + do { + FD_ZERO(&fds); + FD_SET(fd, &fds); + rc = select(fd+1, &fds, NULL, NULL, NULL); + } while (rc == -1 && (errno == EINTR || errno == EAGAIN)); + if (rc < 0) + { + net_errno = errno; + return(-1); /* error */ + } +#endif + + newfd = accept(fd, (struct sockaddr*)cli_addr, &clilen); + } while (newfd == -1 && (errno == EINTR || errno == EAGAIN)); + + if (newfd < 0) + { + net_errno = errno; + return(-1); /* error */ + } + + return newfd; +} int upserror, syserrno; --- ./include/apc_nis.h Tue May 28 09:34:24 2002 +++ ./apcupsd-3.10.11-debug3/include/apc_nis.h Fri Feb 6 21:19:14 2004 @@ -40,4 +40,7 @@ /* Close the network connection */ void net_close(int sockfd); +/* Wait for and accept a new TCP connection */ +int net_accept(int fd, struct sockaddr_in *cli_addr); + extern int upserror, syserrno; --------------000001020500010208080609--