Subject: pkg/6010: most fatal errors in pkg_install progs are unreachable
To: None <gnats-bugs@gnats.netbsd.org>
From: None <jbernard@ox.mines.edu>
List: netbsd-bugs
Date: 08/23/1998 21:35:28
>Number:         6010
>Category:       pkg
>Synopsis:       most fatal errors in pkg_install progs are unreachable
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Aug 23 20:50:00 1998
>Last-Modified:
>Originator:     Jim Bernard
>Organization:
	Speaking for myself
>Release:        August 22, 1998
>Environment:
System: NetBSD zoo 1.3F NetBSD 1.3F (ZOO) #0: Sun Jun 14 09:09:08 MDT 1998 local@zoo:/home/local/compile/sys/arch/i386/compile/ZOO i386


>Description:
	There are numerous places in the pkg_install programs where
	fatal errors are trapped, the cleanup() function is called,
	and the code intends then to exit with an error message generated
	by errx.  However, all the cleanup() functions have had an
	exit(1) stuck in them, so they never return and the error messages
	are never printed.  Not very friendly.

>How-To-Repeat:
	Do something that generates an error and wonder what went wrong
	and why no information at all was provided on the nature of the
	problem.  E.g., if the patches from PR 6009 have not been applied
	(adds support for symbolic links in PREFIX), make PREFIX a symbolic
	link and try to pkg_add a binary package.  It will completely silently
	fail to add the package, giving no clue as to the problem.

>Fix:
	These patches remove the exit() call from the various cleanup()
	functions, except in the case where they are called in response
	to receipt of a signal.  All the changed files are in subdirs of
	usr.sbin/pkg_install (lib/msg.c, add/perform.c, create/perform.c,
	delete/perform.c, and info/perform.c).

	The lib/msg.c file contained some calls to cleanup that _did_ assume
	that cleanup() would exit, in contrast to the multitude of other
	calls to cleanup(), so these were changed to expect it not to exit.

	There was originally protection against multiple calls to cleanup()
	in add/perform.c, on account of the fact that leave_playpen(),
	which is called by cleanup(), can, in turn, call cleanup().  I
	extended that to the other cleanup() functions, where they too
	called leave_playpen.

	In addition, there's the (small) possibility of a signal being
	received while cleanup() is in progress, so in those programs
	where signals were being caught, I changed cleanup() to ignore
	them during its execution (in every case the code exits shortly
	after cleanup(), so there should be no problem with this).

	After applying these patches, voila! you will see error messages
	again.

--- lib/msg.c-dist	Fri Oct 17 13:24:52 1997
+++ lib/msg.c	Sun Aug 23 20:58:05 1998
@@ -33,14 +33,14 @@
 #include <err.h>
 #include "lib.h"
 
 /* Die a relatively simple death */
 void
-upchuck(const char *err)
+upchuck(const char *errstr)
 {
-    warn("fatal error during execution: %s", err);
     cleanup(0);
+    err(1, "fatal error during execution: %s", errstr);
 }
 
 /*
  * As a yes/no question, prompting from the varargs string and using
  * default if user just hits return.
@@ -57,12 +57,12 @@
      * Need to open /dev/tty because file collection may have been
      * collected on stdin
      */
     tty = fopen("/dev/tty", "r");
     if (!tty) {
-	warnx("can't open /dev/tty!");
 	cleanup(0);
+	errx(1, "can't open /dev/tty!");
     }
     while (ch != 'Y' && ch != 'N') {
 	vfprintf(stderr, msg, args);
 	if (def)
 	    fprintf(stderr, " [yes]? ");
--- add/perform.c-dist	Mon Jul 13 05:17:48 1998
+++ add/perform.c	Sun Aug 23 08:37:26 1998
@@ -493,16 +493,23 @@
 
 void
 cleanup(int signo)
 {
     static int	alreadyCleaning;
+    void (*oldint)(int);
+    void (*oldhup)(int);
+    oldint = signal(SIGINT, SIG_IGN);
+    oldhup = signal(SIGHUP, SIG_IGN);
 
     if (!alreadyCleaning) {
     	alreadyCleaning = 1;
 	if (signo)
-		printf("Signal %d received, cleaning up..\n", signo);
+	    printf("Signal %d received, cleaning up..\n", signo);
 	if (!Fake && LogDir[0])
-		vsystem("%s -rf %s", REMOVE_CMD, LogDir);
+	    vsystem("%s -rf %s", REMOVE_CMD, LogDir);
 	leave_playpen(Home);
+	if (signo)
+	    exit(1);
     }
-    exit(1);
+    signal(SIGINT, oldint);
+    signal(SIGHUP, oldhup);
 }
--- create/perform.c-dist	Sat Jun  6 05:21:57 1998
+++ create/perform.c	Sun Aug 23 20:33:39 1998
@@ -312,8 +312,22 @@
 
 /* Clean up those things that would otherwise hang around */
 void
 cleanup(int sig)
 {
-    leave_playpen(home);
-    exit(1);
+    static int	alreadyCleaning;
+    void (*oldint)(int);
+    void (*oldhup)(int);
+    oldint = signal(SIGINT, SIG_IGN);
+    oldhup = signal(SIGHUP, SIG_IGN);
+
+    if (!alreadyCleaning) {
+    	alreadyCleaning = 1;
+	if (sig)
+	    printf("Signal %d received, cleaning up..\n", sig);
+	leave_playpen(home);
+	if (sig)
+	    exit(1);
+    }
+    signal(SIGINT, oldint);
+    signal(SIGHUP, oldhup);
 }
--- delete/perform.c-dist	Fri Oct 17 13:24:05 1997
+++ delete/perform.c	Sun Aug 23 20:38:44 1998
@@ -166,11 +166,11 @@
 
 void
 cleanup(int sig)
 {
     /* Nothing to do */
-    exit(1);
+    return;
 }
 
 static void
 undepend(PackingList p, char *pkgname)
 {
--- info/perform.c-dist	Fri Jul 10 05:17:07 1998
+++ info/perform.c	Sun Aug 23 20:34:30 1998
@@ -245,8 +245,19 @@
 }
 
 void
 cleanup(int sig)
 {
-    leave_playpen(Home);
-    exit(1);
+    static int	alreadyCleaning;
+    void (*oldint)(int);
+    oldint = signal(SIGINT, SIG_IGN);
+
+    if (!alreadyCleaning) {
+    	alreadyCleaning = 1;
+	if (sig)
+	    printf("Signal %d received, cleaning up..\n", sig);
+	leave_playpen(Home);
+	if (sig)
+	    exit(1);
+    }
+    signal(SIGINT, oldint);
 }
>Audit-Trail:
>Unformatted: