From donn@u.washington.edu Fri May 23 14:58:12 1997
Received: from MIT.EDU (PACIFIC-CARRIER-ANNEX.MIT.EDU [18.69.0.28]) by rt-11.MIT.EDU (8.7.5/8.7.3) with SMTP id OAA20796 for <bugs@RT-11.MIT.EDU>; Fri, 23 May 1997 14:58:11 -0400
Received: from melville.u.washington.edu by MIT.EDU with SMTP
id AB06165; Fri, 23 May 97 14:57:24 EDT
Received: (from donn@localhost)
by melville.u.washington.edu (8.8.4+UW97.04/8.8.4+UW97.05)
id LAA153034; Fri, 23 May 1997 11:58:05 -0700
Message-Id: <199705231858.LAA153034@melville.u.washington.edu>
Date: Fri, 23 May 1997 11:58:05 -0700
From: donn@u.washington.edu
Reply-To: donn@u.washington.edu
To: krb5-bugs@MIT.EDU
Subject: bsd/login.c steals SIGHUP
X-Send-Pr-Version: 3.99
University of Washington
System: AIX melville 2 4 000010504900
parent process remains the tty session leader and receives the SIGHUP
when the connection closes. Normally, the shell receives this signal,
and passes it on to its child process groups (if it's a job control
shell that would have child processes in different process groups.)
This is needed to terminate processes that would otherwise loop on
a non-blocking tty read, processes that would keep lock files and other
resources. I believe login.krb5 is also unable to clean up the
Kerberos credential cache anyway, because it dies on the SIGHUP.
close the connection (I did this from an NCD X terminal builtin
telnet, which provides a menu with that option.) In an environment
that uses the standard login, a.out will abort due to signal 1, and
the shell will also be gone. In the krb5-1.0pl1 environment,
login.krb5 will disappear but the shell and a.out will still be
running.
#include <signal.h>
#include <stdio.h>
static void
catch(int sig)
{
printf("Signal %d\n", sig);
exit(0);
}
main(int argc, char **argv)
{
sigset_t nmask;
signal(SIGHUP, catch);
sigemptyset(&nmask);
sigsuspend(&nmask);
perror("sigsuspend");
}
catching the SIGHUP and passing it to the child process group.
(NB., process group not process - process will work with job control
shells like ksh & csh, because they emulate a process group kill
by passing the HUP along to at least the foreground job. Process
*group* is required for non-job-control shells, e.g. miscellaneous
menus and whatnot running as login shells.) This may take an
autoconfig dependency like HAVE_KILLPG (kill(-pid, SIGHUP) is
the same effect, but maybe harder to autoconfig.)
I tried pretty hard to transfer the tty session leadership to
the shell process. That would probably be the ideal thing, but
I couldn't get it to happen, on Digital UNIX at any rate. I think
it's not going to be possible to make this work on all UNIXes.
Donn Cave, University Computing Services, University of Washington
donn@u.washington.edu
-----------------------------
*** src/appl/bsd/login.c.dist Wed Apr 2 23:35:11 1997
--- src/appl/bsd/login.c Fri May 23 11:13:14 1997
***************
*** 2386,2391 ****
--- 2386,2398 ----
}
#if defined(KRB4_GET_TICKETS) || defined(KRB5_GET_TICKETS)
+
+ static int hungup = 0;
+ static sigtype
+ sighup() {
+ hungup = 1;
+ }
+
/* call already conditionalized on login_krb4_get_tickets */
/*
* This routine handles cleanup stuff, and the like.
***************
*** 2396,2401 ****
--- 2403,2409 ----
dofork()
{
int child;
+ handler sa;
#ifdef _IBMR2
update_ref_count(1);
***************
*** 2433,2447 ****
(void) chdir("/"); /* Let's not keep the fs busy... */
/* If we're the parent, watch the child until it dies */
#ifdef HAVE_WAITPID
! (void)waitpid(child, 0, 0);
#else
#ifdef WAIT_USES_INT
! while(wait((int *)0) != child) /*void*/ ;
#else
! while(wait((union wait *)0) != child) /*void*/ ;
#endif
#endif
/* Cleanup stuff */
/* Run destroy_tickets to destroy tickets */
--- 2441,2463 ----
(void) chdir("/"); /* Let's not keep the fs busy... */
/* If we're the parent, watch the child until it dies */
+ /* On receipt of SIGHUP, pass that along to child's process group. */
+
+ handler_init (sa, sighup);
+ handler_set (SIGHUP, sa);
+
#ifdef HAVE_WAITPID
! if (waitpid(child, 0, 0) < 0) {
#else
#ifdef WAIT_USES_INT
! while(wait((int *)0) != child) {
#else
! while(wait((union wait *)0) != child) {
#endif
#endif
+ if (hungup)
+ killpg(child, SIGHUP);
+ }
/* Cleanup stuff */
/* Run destroy_tickets to destroy tickets */
State-Changed-From-To: open-closed
State-Changed-By: tytso
State-Changed-When: Fri Jun 6 22:35:51 1997
State-Changed-Why: suggestion applied to sources
Received: from MIT.EDU (PACIFIC-CARRIER-ANNEX.MIT.EDU [18.69.0.28]) by rt-11.MIT.EDU (8.7.5/8.7.3) with SMTP id OAA20796 for <bugs@RT-11.MIT.EDU>; Fri, 23 May 1997 14:58:11 -0400
Received: from melville.u.washington.edu by MIT.EDU with SMTP
id AB06165; Fri, 23 May 97 14:57:24 EDT
Received: (from donn@localhost)
by melville.u.washington.edu (8.8.4+UW97.04/8.8.4+UW97.05)
id LAA153034; Fri, 23 May 1997 11:58:05 -0700
Message-Id: <199705231858.LAA153034@melville.u.washington.edu>
Date: Fri, 23 May 1997 11:58:05 -0700
From: donn@u.washington.edu
Reply-To: donn@u.washington.edu
To: krb5-bugs@MIT.EDU
Subject: bsd/login.c steals SIGHUP
X-Send-Pr-Version: 3.99
Show quoted text
>Number: 432
>Category: krb5-appl
>Synopsis: login.krb5 gets tty SIGHUP, instead of shell.
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: krb5-unassigned
>State: closed
>Class: sw-bug
>Submitter-Id: unknown
>Arrival-Date: Fri May 23 14:59:00 EDT 1997
>Last-Modified: Fri Jun 06 22:36:07 EDT 1997
>Originator: Donn Cave
>Organization:
University Computing Services>Category: krb5-appl
>Synopsis: login.krb5 gets tty SIGHUP, instead of shell.
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: krb5-unassigned
>State: closed
>Class: sw-bug
>Submitter-Id: unknown
>Arrival-Date: Fri May 23 14:59:00 EDT 1997
>Last-Modified: Fri Jun 06 22:36:07 EDT 1997
>Originator: Donn Cave
>Organization:
University of Washington
Show quoted text
>Release: 1.0pl1
>Environment:
Digital UNIX 4.0a, AIX 4.2>Environment:
System: AIX melville 2 4 000010504900
Show quoted text
>Description:
Because login.krb5 execs the shell in a child process, the login.krb5parent process remains the tty session leader and receives the SIGHUP
when the connection closes. Normally, the shell receives this signal,
and passes it on to its child process groups (if it's a job control
shell that would have child processes in different process groups.)
This is needed to terminate processes that would otherwise loop on
a non-blocking tty read, processes that would keep lock files and other
resources. I believe login.krb5 is also unable to clean up the
Kerberos credential cache anyway, because it dies on the SIGHUP.
Show quoted text
>How-To-Repeat:
Run the following program (e.g., ./a.out > hupout 2>&1) and thenclose the connection (I did this from an NCD X terminal builtin
telnet, which provides a menu with that option.) In an environment
that uses the standard login, a.out will abort due to signal 1, and
the shell will also be gone. In the krb5-1.0pl1 environment,
login.krb5 will disappear but the shell and a.out will still be
running.
#include <signal.h>
#include <stdio.h>
static void
catch(int sig)
{
printf("Signal %d\n", sig);
exit(0);
}
main(int argc, char **argv)
{
sigset_t nmask;
signal(SIGHUP, catch);
sigemptyset(&nmask);
sigsuspend(&nmask);
perror("sigsuspend");
}
Show quoted text
>Fix:
The appended patch takes what I think is the most direct approach,catching the SIGHUP and passing it to the child process group.
(NB., process group not process - process will work with job control
shells like ksh & csh, because they emulate a process group kill
by passing the HUP along to at least the foreground job. Process
*group* is required for non-job-control shells, e.g. miscellaneous
menus and whatnot running as login shells.) This may take an
autoconfig dependency like HAVE_KILLPG (kill(-pid, SIGHUP) is
the same effect, but maybe harder to autoconfig.)
I tried pretty hard to transfer the tty session leadership to
the shell process. That would probably be the ideal thing, but
I couldn't get it to happen, on Digital UNIX at any rate. I think
it's not going to be possible to make this work on all UNIXes.
Donn Cave, University Computing Services, University of Washington
donn@u.washington.edu
-----------------------------
*** src/appl/bsd/login.c.dist Wed Apr 2 23:35:11 1997
--- src/appl/bsd/login.c Fri May 23 11:13:14 1997
***************
*** 2386,2391 ****
--- 2386,2398 ----
}
#if defined(KRB4_GET_TICKETS) || defined(KRB5_GET_TICKETS)
+
+ static int hungup = 0;
+ static sigtype
+ sighup() {
+ hungup = 1;
+ }
+
/* call already conditionalized on login_krb4_get_tickets */
/*
* This routine handles cleanup stuff, and the like.
***************
*** 2396,2401 ****
--- 2403,2409 ----
dofork()
{
int child;
+ handler sa;
#ifdef _IBMR2
update_ref_count(1);
***************
*** 2433,2447 ****
(void) chdir("/"); /* Let's not keep the fs busy... */
/* If we're the parent, watch the child until it dies */
#ifdef HAVE_WAITPID
! (void)waitpid(child, 0, 0);
#else
#ifdef WAIT_USES_INT
! while(wait((int *)0) != child) /*void*/ ;
#else
! while(wait((union wait *)0) != child) /*void*/ ;
#endif
#endif
/* Cleanup stuff */
/* Run destroy_tickets to destroy tickets */
--- 2441,2463 ----
(void) chdir("/"); /* Let's not keep the fs busy... */
/* If we're the parent, watch the child until it dies */
+ /* On receipt of SIGHUP, pass that along to child's process group. */
+
+ handler_init (sa, sighup);
+ handler_set (SIGHUP, sa);
+
#ifdef HAVE_WAITPID
! if (waitpid(child, 0, 0) < 0) {
#else
#ifdef WAIT_USES_INT
! while(wait((int *)0) != child) {
#else
! while(wait((union wait *)0) != child) {
#endif
#endif
+ if (hungup)
+ killpg(child, SIGHUP);
+ }
/* Cleanup stuff */
/* Run destroy_tickets to destroy tickets */
Show quoted text
>Audit-Trail:
State-Changed-From-To: open-closed
State-Changed-By: tytso
State-Changed-When: Fri Jun 6 22:35:51 1997
State-Changed-Why: suggestion applied to sources
Show quoted text
>Unformatted: