Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 23 Aug 2009 00:07:53 -0400
From:      Nathan Lay <nslay@comcast.net>
To:        Ed Schouten <ed@80386.nl>
Cc:        freebsd-current@FreeBSD.org, Jeremie Le Hen <jeremie@le-hen.org>
Subject:   Re: truss(1) locked in kernel with 8.0-BETA2
Message-ID:  <4A90C099.8030605@comcast.net>
In-Reply-To: <20090822194009.GQ1292@hoeg.nl>
References:  <20090822185812.GC61707@felucia.tataz.chchile.org> <20090822194009.GQ1292@hoeg.nl>

next in thread | previous in thread | raw e-mail | index | archive | help
Ed Schouten wrote:
> Hi Jeremie,
>
> * Jeremie Le Hen <jeremie@le-hen.org> wrote:
>   
>> I've upgraded my laptop to 8.0-BETA2 and ran portupgrade in script(1).
>> But according to top, it seems script(1) is going crazy, even after I've
>> hit ^C:
>>     
>
> The fact that script(1) is going crazy, is a known issue. I have been
> pointed to this issue earlier, but unfortunately I don't know what to
> do. A certain Colin introduced this bug about 6 years ago. ;-)
>
> It's basically a shortcoming of pseudo-terminals in general. script(1)
> wants to behave in a way which cannot be implemented using
> pseudo-terminals; when it receives a hangup on its standard input (on
> the outside), it wants to propagate the end-of-file condition and wants
> to continue until the child processes are finished, instead of shutting
> down immediately. So a couple of milliseconds later on, it calls
> select(2) again, but because the TTY it uses on the outside is still in
> a hangup condition, select(2) returns immediately.
>
> This can easily be reproduced as follows:
>
> 	script < /dev/null
>
> I think the only way we can sanely fix this, is by adding a special flag
> to instruct script(1) to keep going on, even if stdin disappears. I
> wrote a patch for this back in May:
>
> 	http://80386.nl/pub/script.diff
>
> Thanks for reminding me. I should contact re@ about this.
>
>   
Instead of zeroing and setting master and STDIN_FILENO on the fd_set 
every iteration, why not have two fd_sets: the original and temporary.  
At every iteration the original is copied into the temporary for 
select() to destroy.  Once the hangup condition is detected, the 
STDIN_FILENO is cleared from the original fd_set so it will not be 
examined by select() later.  For example:

fd_set rfds, tmpfds;

FD_ZERO(&rfds);
FD_SET(master,&rfds);
FD_SET(STDIN_FILENO,&rfds);

for (;;) {
    tmpfds = rfds; /* Not sure if this assignment is portable */
    n = select(master+1, &tmpfds, NULL, NULL, tvp);
    if (hangup condition) {
       FD_CLR(STDIN_FILENO,&rfds);
    }
    /* Do other stuff here */
}

Best Regards,
Nathan Lay




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4A90C099.8030605>