From seggers@semyam.dinoco.de  Mon Jun 22 07:23:15 1998
Received: from tim.xenologics.com (tim.xenologics.com [194.77.5.24])
          by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id HAA06754
          for <FreeBSD-gnats-submit@freebsd.org>; Mon, 22 Jun 1998 07:23:09 -0700 (PDT)
          (envelope-from seggers@semyam.dinoco.de)
Received: (from uucp@localhost)
	by tim.xenologics.com (8.8.5/8.8.8) with UUCP id QAA07167
	for FreeBSD-gnats-submit@freebsd.org; Mon, 22 Jun 1998 16:18:40 +0200 (MET DST)
Received: (from seggers@localhost)
	by semyam.dinoco.de (8.8.8/8.8.8) id LAA20448;
	Mon, 22 Jun 1998 11:37:19 +0200 (CEST)
	(envelope-from seggers)
Message-Id: <199806220937.LAA20448@semyam.dinoco.de>
Date: Mon, 22 Jun 1998 11:37:19 +0200 (CEST)
From: Stefan Eggers <seggers@semyam.dinoco.de>
Reply-To: seggers@semyam.dinoco.de
To: FreeBSD-gnats-submit@freebsd.org
Cc: seggers@semyam.dinoco.de
Subject: pkg_*'s error handling is broken
X-Send-Pr-Version: 3.2

>Number:         7020
>Category:       bin
>Synopsis:       pkg_*'s error handling is broken
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    jkh
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jun 22 07:30:00 PDT 1998
>Closed-Date:    Tue Jul 28 04:55:44 PDT 1998
>Last-Modified:  Tue Jul 28 04:56:08 PDT 1998
>Originator:     Stefan Eggers
>Release:        FreeBSD 2.2.6-STABLE i386
>Organization:
none
>Environment:

	My little 2.2-stable system.  CVSUp'ed last weekend.

>Description:

	While improving pkg_create I discovered that the error
handling of pkg_create (and the other pkg_*, too) is seriously broken.
It will never print an error message about certain errors to the user
thus making him/her wonder why it failed.

	The problem is the statement "cleanup(0), errx(1, "ABC");"
- cleanup() does an exit(1) at its end in all cases.  The errx() will
never get executed.  And as the errx() is the only place printing an
error message ...

	I also saw the variable in_cleanup in it which is automatic
and gets initialized to 0.  The next thing done there is testing if
this variable is not set.  Probably this variable should have been
static but I'll have to take a closer look at it to be sure.

	The former problem at least exists in pkg_add, too.  I did not
look at the other pkg_*, yet.  The latter problem does not exist there
- the variable is static.

>How-To-Repeat:

	Just take a look at the code.

>Fix:
	
	Not sure about how to best fix it.  If all cleanup() calls
get followed by errx() it will be safe to just remove the exit().
This will break its use as signal handler.  A signalcleanup() should
be added which calls the old cleanup() and then does the exit() I
think.

	The variable in cleanup() serve as a flag so that it doesn't
get called from the program and at the same time by the signal
processing.  Making it static should fix this problem and make it
actually work as intended.
>Release-Note:
>Audit-Trail:

From: Stefan Eggers <seggers@semyam.dinoco.de>
To: FreeBSD-gnats-submit@FreeBSD.ORG
Cc: seggers@semyam.dinoco.de
Subject: Re: bin/7020: pkg_*'s error handling is broken 
Date: Mon, 22 Jun 1998 20:24:40 +0200

 Hi!
 
 Now I have a diff ready to fix the problem.  If a context diff is
 preferable I'll make those the next time I send something in.
 
 Stefan.
 
 
 diff -ru pkg_install/add/perform.c pkg_install.NEW/add/perform.c
 --- pkg_install/add/perform.c	Mon Feb 16 18:41:31 1998
 +++ pkg_install.NEW/add/perform.c	Mon Jun 22 20:06:06 1998
 @@ -39,8 +39,8 @@
  {
      int i, err_cnt = 0;
  
 -    signal(SIGINT, cleanup);
 -    signal(SIGHUP, cleanup);
 +    signal(SIGINT, signalcleanup);
 +    signal(SIGHUP, signalcleanup);
  
      if (AddMode == SLAVE)
  	err_cnt = pkg_do(NULL);
 @@ -480,5 +480,11 @@
  		vsystem("%s -rf %s", REMOVE_CMD, LogDir);
      	leave_playpen();
      }
 +}
 +
 +void
 +signalcleanup(int signo)
 +{
 +    cleanup(signo);
      exit(1);
  }
 diff -ru pkg_install/create/perform.c pkg_install.NEW/create/perform.c
 --- pkg_install/create/perform.c	Mon Feb 16 18:41:38 1998
 +++ pkg_install.NEW/create/perform.c	Mon Jun 22 20:11:09 1998
 @@ -118,8 +118,8 @@
  
      /* Make a directory to stomp around in */
      home = make_playpen(PlayPen, 0);
 -    signal(SIGINT, cleanup);
 -    signal(SIGHUP, cleanup);
 +    signal(SIGINT, signalcleanup);
 +    signal(SIGHUP, signalcleanup);
  
      /* Make first "real contents" pass over it */
      check_list(home, &plist);
 @@ -288,13 +288,21 @@
  
  /* Clean up those things that would otherwise hang around */
  void
 -cleanup(int sig)
 +cleanup(int signo)
  {
 -    int in_cleanup = 0;
 +    static int in_cleanup = 0;
  
      if (!in_cleanup) {
  	in_cleanup = 1;
 +    	if (signo)
 +		printf("Signal %d received, cleaning up..\n", signo);
      	leave_playpen();
      }
 +}
 +
 +void
 +signalcleanup(int signo)
 +{
 +    cleanup(signo);
      exit(1);
  }
 diff -ru pkg_install/delete/perform.c pkg_install.NEW/delete/perform.c
 --- pkg_install/delete/perform.c	Mon Oct 13 17:06:12 1997
 +++ pkg_install.NEW/delete/perform.c	Mon Jun 22 20:10:09 1998
 @@ -162,7 +162,6 @@
  cleanup(int sig)
  {
      /* Nothing to do */
 -    exit(1);
  }
  
  static void
 diff -ru pkg_install/info/perform.c pkg_install.NEW/info/perform.c
 --- pkg_install/info/perform.c	Mon Feb 16 18:41:44 1998
 +++ pkg_install.NEW/info/perform.c	Mon Jun 22 20:16:35 1998
 @@ -36,7 +36,8 @@
      int i, err_cnt = 0;
      char *tmp;
  
 -    signal(SIGINT, cleanup);
 +    signal(SIGINT, signalcleanup);
 +    signal(SIGHUP, signalcleanup);
  
      tmp = getenv(PKG_DBDIR);
      if (!tmp)
 @@ -207,5 +208,11 @@
  	in_cleanup = 1;
      	leave_playpen();
      }
 +}
 +
 +void
 +signalcleanup(int sig)
 +{
 +    cleanup(sig);
      exit(1);
  }
 diff -ru pkg_install/lib/lib.h pkg_install.NEW/lib/lib.h
 --- pkg_install/lib/lib.h	Mon Feb 16 18:41:51 1998
 +++ pkg_install.NEW/lib/lib.h	Mon Jun 22 16:19:30 1998
 @@ -106,6 +106,7 @@
  /* Misc */
  int		vsystem(const char *, ...);
  void		cleanup(int);
 +void		signalcleanup(int);
  char		*make_playpen(char *, size_t);
  char		*where_playpen(void);
  void		leave_playpen(void);
 diff -ru pkg_install/lib/msg.c pkg_install.NEW/lib/msg.c
 --- pkg_install/lib/msg.c	Mon Mar  9 13:31:15 1998
 +++ pkg_install.NEW/lib/msg.c	Mon Jun 22 16:27:42 1998
 @@ -33,6 +33,7 @@
  {
      warn("fatal error during execution: %s", err);
      cleanup(0);
 +    exit(1);
  }
  
  /*
 @@ -55,6 +56,7 @@
      if (!tty) {
  	warnx("can't open /dev/tty!");
  	cleanup(0);
 +        exit(1);
      }
      while (ch != 'Y' && ch != 'N') {
  	vfprintf(stderr, msg, args);
Responsible-Changed-From-To: freebsd-bugs->asami 
Responsible-Changed-By: phk 
Responsible-Changed-When: Wed Jun 24 00:58:35 PDT 1998 
Responsible-Changed-Why:  
-> asami-san 
Responsible-Changed-From-To: asami->jkh 
Responsible-Changed-By: asami 
Responsible-Changed-When: Thu Jun 25 18:32:17 PDT 1998 
Responsible-Changed-Why:  
Um, this is Jordan's code. 
State-Changed-From-To: open->closed 
State-Changed-By: jkh 
State-Changed-When: Tue Jul 28 04:55:44 PDT 1998 
State-Changed-Why:  
Actually, the required fix was far easier - just one line change. :) 
Thanks for pointing this out. 
>Unformatted:
