Terminal messed up after exiting bash

2014-09-08 Thread Jan Rome

Hello,

I'd like to report an obscure bug I came across in pfsense which runs on 
top of FreeBSD.


If I run a bash script in which I have

read -r -n1 -p "prompt: "

and instead of providing input, i ctrl-c the script,

the ash shell doesn't recover the terminal properly; backspace echos ^? 
and the only way to delete characters is to hold shift and press 
backspace. Also,  if I use the -s switch for the read command in the 
bash script, the problem gets even worse with the cursor not moving 
anymore as I type and the text I type not being visible at all.


A solution was provided by pgas from #bash on irc.freenode.net, where I 
solve this by trapping the ctrl-c signal and do 'stty cooked' before 
exiting, which seems to give expected behaviour.


Best regards,

Jan



Re: read -e does not restore terminal settings correctly when interrupted if a trap is set

2014-09-08 Thread Chet Ramey
On 9/7/14, 6:40 PM, micka...@gmail.com wrote:

> Bash Version: 4.3
> Patch Level: 24
> Release Status: release
> 
> Description:
>   Given the following script (test.sh) :
> 
>   #!/bin/bash
>   cleanup() { :; }
>   trap cleanup 0
>   read -e dummy
> 
>   Run the script ('bash test.sh') *in ZSH* and when it waits for an input,
>   interrupt it with Ctrl-C.

Thanks for the report.  The problem is that bash doesn't clean up readline
and its terminal state in all cases that can result in its calling
longjmp() or exiting the shell.  I've attached a patch that should fix the
problem.

The problem doesn't manifest itself in bash because bash saves the terminal
state before a command runs and restores it when the command is terminated
by a signal.

Chet


-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
*** ../bash-4.3-patched/bashline.c	2014-05-14 09:22:39.0 -0400
--- bashline.c	2014-09-08 11:28:56.0 -0400
***
*** 203,206 
--- 203,207 
  extern int array_needs_making;
  extern int posixly_correct, no_symbolic_links;
+ extern int sigalrm_seen;
  extern char *current_prompt_string, *ps1_prompt;
  extern STRING_INT_ALIST word_token_alist[];
***
*** 4209,4214 
/* If we're going to longjmp to top_level, make sure we clean up readline.
   check_signals will call QUIT, which will eventually longjmp to top_level,
!  calling run_interrupt_trap along the way. */
!   if (interrupt_state)
  rl_cleanup_after_signal ();
bashline_reset_event_hook ();
--- 4262,4268 
/* If we're going to longjmp to top_level, make sure we clean up readline.
   check_signals will call QUIT, which will eventually longjmp to top_level,
!  calling run_interrupt_trap along the way.  The check for sigalrm_seen is
!  to clean up the read builtin's state. */
!   if (terminating_signal || interrupt_state || sigalrm_seen)
  rl_cleanup_after_signal ();
bashline_reset_event_hook ();
*** ../bash-4.3-patched/sig.c	2014-01-10 15:06:06.0 -0500
--- sig.c	2014-09-08 11:26:33.0 -0400
***
*** 533,538 
/* Set the event hook so readline will call it after the signal handlers
   finish executing, so if this interrupted character input we can get
!  quick response. */
!   if (interactive_shell && interactive && no_line_editing == 0)
  bashline_set_event_hook ();
  #endif
--- 533,540 
/* Set the event hook so readline will call it after the signal handlers
   finish executing, so if this interrupted character input we can get
!  quick response.  If readline is active or has modified the terminal we
!  need to set this no matter what the signal is, though the check for
!  RL_STATE_TERMPREPPED is possibly redundant. */
!   if (RL_ISSTATE (RL_STATE_SIGHANDLER) || RL_ISSTATE (RL_STATE_TERMPREPPED))
  bashline_set_event_hook ();
  #endif


Re: read -e does not restore terminal settings correctly when interrupted if a trap is set

2014-09-08 Thread Mickaƫl THOMAS
Yep, that fixed the problem, thank you !

2014-09-08 20:46 GMT+02:00 Chet Ramey :
> On 9/7/14, 6:40 PM, micka...@gmail.com wrote:
>
>> Bash Version: 4.3
>> Patch Level: 24
>> Release Status: release
>>
>> Description:
>>   Given the following script (test.sh) :
>>
>>   #!/bin/bash
>>   cleanup() { :; }
>>   trap cleanup 0
>>   read -e dummy
>>
>>   Run the script ('bash test.sh') *in ZSH* and when it waits for an 
>> input,
>>   interrupt it with Ctrl-C.
>
> Thanks for the report.  The problem is that bash doesn't clean up readline
> and its terminal state in all cases that can result in its calling
> longjmp() or exiting the shell.  I've attached a patch that should fix the
> problem.
>
> The problem doesn't manifest itself in bash because bash saves the terminal
> state before a command runs and restores it when the command is terminated
> by a signal.
>
> Chet
>
>
> --
> ``The lyf so short, the craft so long to lerne.'' - Chaucer
>  ``Ars longa, vita brevis'' - Hippocrates
> Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Trap not being run for all CHLD signals, 4.3

2014-09-08 Thread Chet Ramey
On 9/3/14, 10:08 AM, crispusfairba...@gmail.com wrote:
> $ cat parallel-test.bash
> function process_job {
> sleep 1
> }
> 
> function main {
> typeset -i index=0 cur_jobs=0 max_jobs=6
> trap '((cur_jobs--))' CHLD
> set -m
> 
> while ((index++ < 30)); do
> echo -n "index: $index, cur_jobs: $cur_jobs"
> set +m
> childs=$(pgrep -P $$ | wc -w)
> (( childs < cur_jobs )) && echo -n ", actual childs: $childs"
> echo
> set -m
> process_job &
> ((++cur_jobs >= max_jobs)) && POSIXLY_CORRECT= wait;
> done
> 
> echo 'finished, waiting for remaining jobs...'
> wait
> }
> 
> main
> echo "done"
> 
> This works on:
> GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
> 
> But on:
> GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
> and
> GNU bash, version 4.3.24(1)-release (x86_64-unknown-linux-gnu)
> 
> it will around "index: 9" start missing traps (not decrementing cur_jobs):
> 
> $ bash-4.3.24/bin/bash parallel-test.bash
> index: 1, cur_jobs: 0
> index: 2, cur_jobs: 1
> index: 3, cur_jobs: 2
> index: 4, cur_jobs: 3
> index: 5, cur_jobs: 4
> index: 6, cur_jobs: 5
> index: 7, cur_jobs: 5
> index: 8, cur_jobs: 5
> index: 9, cur_jobs: 5, actual childs: 4
> index: 10, cur_jobs: 5, actual childs: 3
> index: 11, cur_jobs: 5, actual childs: 3
> ...
> 
> 
> If the sleep is changed to be random, it might work correctly for the whole 
> 30 iterations, which points to a race condition somewhere?

The problem is running the wait builtin in posixly-correct mode.  That
causes the first SIGCHLD to interrupt wait (as Posix requires) and results
in timing issues.

I will look at making SIGCHLD traps more reliable in the face of the Posix
requirements.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Terminal messed up after exiting bash

2014-09-08 Thread Ryan Cunningham
This isn't clear to me. Are you using the Almquist Shell to execute BASH to run 
your script, or is BASH already running when the script is executed?

-- 
Sent from my iPad

> On Sep 8, 2014, at 1:17 AM, Jan Rome  wrote:
> 
> Hello,
> 
> I'd like to report an obscure bug I came across in pfsense which runs on top 
> of FreeBSD.
> 
> If I run a bash script in which I have
> 
> read -r -n1 -p "prompt: "
> 
> and instead of providing input, i ctrl-c the script,
> 
> the ash shell doesn't recover the terminal properly; backspace echos ^? and 
> the only way to delete characters is to hold shift and press backspace. Also, 
>  if I use the -s switch for the read command in the bash script, the problem 
> gets even worse with the cursor not moving anymore as I type and the text I 
> type not being visible at all.
> 
> A solution was provided by pgas from #bash on irc.freenode.net, where I solve 
> this by trapping the ctrl-c signal and do 'stty cooked' before exiting, which 
> seems to give expected behaviour.
> 
> Best regards,
> 
> Jan
> 



Re: RFE: remove duplicate entries from the result of `compgen -W'

2014-09-08 Thread Clark Wang
On Mon, Sep 8, 2014 at 1:07 AM, Chet Ramey  wrote:

> On 9/4/14, 10:33 PM, Clark Wang wrote:
> > See following example:
> >
> >   $ echo $BASH_VERSION
> >   4.3.18(1)-release
> >   $ compgen -W 'hello hello' h
> >   hello
> >   hello
> >   $
> >
> > It'll be good if only one "hello" is outputted.
>
> `complete' and `compgen' only generate lists of possible completions.
> Readline performs duplicate removal when it is deciding what to do
> with that list.
>

Thanks, Chet. I did not realized this.

In the following example I'll describe my use case and you can understand
why my requirement.

Many commands like ping and ssh would take a hostname as their parameter.
I'm trying to define a common compspec for all these commands since
bash-4.1 added the `complete -D' option which is very cool. My idea is just
like bash's builtin completion behavior when we input `@' but I'd like
the `@' char to be automatically removed when there's only one host
matching. See following demo code:

  function compgen_hosts
  {
  local cmd=$1
  local cur=$2
  local pre=$3
  local -a hosts
  local host

  hosts=( $(awk '$1 !~ /^ *#/' /etc/hosts) )

  if [[ $cur == @* ]]; then
  host=${cur#*@}
  COMPREPLY=( $( compgen -P @ -W "${hosts[*]}" "$host") )
  fi

  if [[ ${#COMPREPLY[@]} == 1 ]]; then
  COMPREPLY[0]=${COMPREPLY[0]#@}
  fi
  }

  complete -D -o nospace -F compgen_hosts

For most of the time this works fine. For example:

  $ foo @host-
  @host-a.us  @host-b.us
  $ foo @host-a
  $ foo host-a.us

But there's a small problem because there are duplicate hostnames. For
example both `127.0.0.1` and `::1` are mapping to `localhost' and then my
code would not work:

  $ foo @localhost
  @localhost
  $

The reason is the `if [[ ${#COMPREPLY[@]} == 1 ]]' condition. For
`localhost' there are two candidates in COMPREPLY:

  COMPREPLY=( localhost localhost )

I know I can manually remove duplicate entries (either when reading
/etc/hosts or from the output of compgen) but it would be convenient if the
result of compgen has already done that for me. :)

Thanks.

-clark

>
> Chet
>
> --
> ``The lyf so short, the craft so long to lerne.'' - Chaucer
>  ``Ars longa, vita brevis'' - Hippocrates
> Chet Ramey, ITS, CWRUc...@case.edu
> http://cnswww.cns.cwru.edu/~chet/
>