From owner-freebsd-bugs Wed Feb 7 18:30:22 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 9ADEC37B401 for ; Wed, 7 Feb 2001 18:30:02 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id f182U2r62479; Wed, 7 Feb 2001 18:30:02 -0800 (PST) (envelope-from gnats) Date: Wed, 7 Feb 2001 18:30:02 -0800 (PST) Message-Id: <200102080230.f182U2r62479@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: Peter Wemm Subject: Re: misc/24942: tftp client timeout failure Reply-To: Peter Wemm Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org The following reply was made to PR misc/24942; it has been noted by GNATS. From: Peter Wemm To: yxiao@cisco.com Cc: freebsd-gnats-submit@FreeBSD.ORG Subject: Re: misc/24942: tftp client timeout failure Date: Wed, 07 Feb 2001 18:20:54 -0800 yxiao@cisco.com wrote: [..] > >Release: $FreeBSD: src/usr.bin/tftp/tftp.c,v 1.5 1999/08/28 01:06:24 peter Exp > >Environment: > Linux dhcp-171-70-93-24.cisco.com 2.2.14-5.0 #1 Tue Mar 7 21:07:39 EST 2000 i 686 unknown Are you running our tftpd under Linux? Or is that just the send-pr environment? > >Description: > Alarm clock can only fired once. Problem: SIGALRM blocked. The patch below has a couple of problems: > >Fix: > change timer function: > --- tftp.c 2000/08/01 20:38:08 1.2 > +++ tftp.c 2001/02/07 16:18:03 > @@ -455,9 +455,15 @@ > timer(sig) > int sig; > { > + sigset_t sigset; > + int error; > > + //signal(SIGALRM, timer); > + error = sigemptyset(&sigset); > + error |= sigdelset(&sigset, SIGALRM); > + error |= sigprocmask(SIG_SETMASK, &sigset, NULL); > timeout += rexmtval; > - if (timeout >= maxtimeout) { > + if (timeout >= maxtimeout || error) { > printf("Transfer timed out.\n"); > global_errno = ETIMEDOUT; > longjmp(toplevel, -1); sigdelset() to delete a signal from an already empty set is a NOP. It might as well be: error = sigemptyset(&sigset); error |= sigprocmask(SIG_SETMASK, &sigset, NULL); There is also a problem.. if sigemptyset() returned an error, sigset would have undefined contents. And yet you call sigprocmask() anyway. I think a more correct fix would be to use sigsetjmp()/siglongjmp() to save/restore the mask.. However, according to the man pages, that shouldn't be necessary: The setjmp()/longjmp() pairs save and restore the signal mask while _setjmp()/_longjmp() pairs save and restore only the register set and the stack. (See sigprocmask(2).) The sigsetjmp()/siglongjmp() function pairs save and restore the signal mask if the argument savemask is non-zero, otherwise only the register set and the stack are saved. Cheers, -Peter -- Peter Wemm - peter@FreeBSD.org; peter@yahoo-inc.com; peter@netplex.com.au "All of this is for nothing if we don't go to the stars" - JMS/B5 To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message