LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices


Reply
  Search this Thread
Old 06-28-2010, 07:40 AM   #1
leniviy
Member
 
Registered: Jul 2009
Distribution: Archlinux
Posts: 69

Rep: Reputation: 4
bash: Ctrl+C not working in some complex loops


Run the following script in bash and try to interrupt it the with Ctrl+C
Code:
  { echo 1; echo 2; echo 3; } | while read a; do
    echo $a
    { echo 1; echo 2; echo 3; } | while read b; do 
      echo $a-$b
      sleep 1
    done
  done
It won't interrupt. Bug or feature?
In zsh or old plain sh it works.
 
Old 06-28-2010, 08:09 AM   #2
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

What do you mean by "Not working"? Did you expect the script to complete stop running?

Every time you press ctrl-c the while loop the script is in is interrupted (the inner loop, which is then started again with the next entry from the outer loop). Which suggests that ctrl-c is working.

From man bash:
Quote:
while list; do list; done
The while command continuously executes the do list as long as the last command in list returns an exit status of zero
Hope this helps.
 
Old 06-28-2010, 01:01 PM   #3
leniviy
Member
 
Registered: Jul 2009
Distribution: Archlinux
Posts: 69

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by druuna View Post
Did you expect the script to complete stop running?
Yes.. what's wrong with that?

Quote:
Originally Posted by druuna View Post
Every time you press ctrl-c the while loop the script is in is interrupted (the inner loop, which is then started again with the next entry from the outer loop).
Actually, the inner loop is interrupted only once. All subsequent pressings of ctrl-c are ignored.
 
Old 06-28-2010, 01:09 PM   #4
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Try removing the sleep. I have half an idea that bash is sending the interrupt to the sleep and not acting on it itself except in the unlikely event that you send the interrupt when sleep is not running.
 
Old 06-28-2010, 01:21 PM   #5
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

Running your code I can interrupt the inner loop 3 times, the first (outer) loop keeps running:
Code:
$ ./blaat 
1
1-1
1-2    ctrl-c pressed
2
2-1    ctrl-c pressed
3
3-1
3-2
3-3
$
$ cat blaat 
#!/bin/bash

 { echo 1; echo 2; echo 3; } | while read a; do
    echo $a
    { echo 1; echo 2; echo 3; } | while read b; do 
      echo $a-$b
      sleep 1
    done
  done
$
Nothing is ignored, the script keeps running (example is interrupted twice).

The only thing I can come up with I already posted in #2 (the quote from bash).

Last edited by druuna; 06-28-2010 at 01:24 PM.
 
Old 06-28-2010, 01:38 PM   #6
leniviy
Member
 
Registered: Jul 2009
Distribution: Archlinux
Posts: 69

Original Poster
Rep: Reputation: 4
I didn't save a file, just pasted the code into the shell. That's why the difference.
But even when executing a file, ctrl-c still doesn't work as it should.
 
Old 06-29-2010, 01:54 PM   #7
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

I've taken a second look at this and catkin is correct: sleep is the culprit.

A strace on the above mentioned code shows that the sleep command is executed as a child and the ctrl-c is caught by that child process.

This also explains the behavior of the (mother) script: If sleep is not interrupted it has an exit code that is zero, if you do interrupt it it will have a non-zero exit code. This exit code is given as return value to the mother and is picked up by the while loop as the "do list" is done, I can exit the loop and the script will continue.

Up to you to decide if this is "works as designed" or not, but it does explain the behavior.
 
Old 06-29-2010, 03:17 PM   #8
leniviy
Member
 
Registered: Jul 2009
Distribution: Archlinux
Posts: 69

Original Poster
Rep: Reputation: 4
The current bash maintainers have replied to my bugreport:
Quote:
Originally Posted by Chet
Thanks for the report. The key is the shell control structure in a
pipeline calling an external command that dies due to SIGINT. This
will be fixed in bash-4.2.
Honestly, I didn't understand a word.
 
Old 06-29-2010, 10:33 PM   #9
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by leniviy View Post
Honestly, I didn't understand a word.
I don't have crystal clarity either but ...

In the simple case, when a bash script is launched from the command prompt and the user presses Ctrl+C, this generates an interrupt signal (SIGINT) which is sent from the terminal to all processes associated with the terminal. The running bash script receives it and exits.

Getting a little more complicated, when the bash script sets up a pipeline, bash creates a child process for each command in the pipeline. Now there's a potential problem; if the bash script exited on receiving SIGINT and its child processes did not then the children would be orphans (sad!) and worse, could turn into zombies (plenty on zombie processes on the 'net).

To avoid this, when bash sets up a pipeline it also configures itself to ignore SIGINT. Which is great for avoiding zombies but does mean, as you have found out, that the script itself can no longer be killed from the terminal using Ctrl+C.

AFAIK that is how it is from the perspective of bash, controlling terminals, processes and SIGINT. Switching to the bash maintainers' perspective, bash is written in C. I guess "the shell control structure" is actually a C structure (a type of C variable comprising several primitive variable types) which is used to control what bash does with a pipleline (there is probably one such structure per simple command in the pipeline).

Perhaps the maintainer means bash 4.2 will no longer discard any SIGINTs received when it is running a pipeline but will hold them as pending until the pipeline terminates and then action the pending SIGINT(s) in the normal way.

That would be great! It would solve a weakness of shell script as a programming tool dating from the origins of shell script.

Last edited by catkin; 06-29-2010 at 10:36 PM. Reason: Comprehensibility
 
Old 08-20-2012, 03:32 AM   #10
ActiveMan
LQ Newbie
 
Registered: Nov 2007
Posts: 7

Rep: Reputation: 0
Just use trap to exit:

Code:
trap "exit" INT

while true; do
 $*;
done
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
KDE 3.5.9 - Konqueror - keyboard shortcuts ctrl+, and ctrl+. sometimes stop working bhy Linux - Desktop 1 07-26-2008 11:48 AM
Bash Loops UnitedWeFall Programming 8 08-21-2007 06:33 AM
Any way to create bash short cuts (like CTRL+l for clear and Ctrl+D for exit) supersubu123 Linux - General 5 05-30-2007 03:02 AM
bash scripting and loops phoeniks Programming 5 01-24-2005 04:00 PM
bash ctrl+a not working! SteveGodfrey Linux - General 3 09-10-2004 07:48 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 07:15 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration