# Break loop by trapping INT

**URL:** <https://www.ruby-forum.com/t/break-loop-by-trapping-int/115227>\
**Category:** Ruby\
**Created:** [September 22, 2007, 1:06am UTC](https://www.ruby-forum.com/t/break-loop-by-trapping-int/115227 "2007-09-22T01:06:04Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Todd\_ASJacobs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/f17d59/32.png) [@Todd\_ASJacobs](https://www.ruby-forum.com/u/Todd_ASJacobs)\
**Post date:** [September 22, 2007, 1:06am UTC](https://www.ruby-forum.com/t/break-loop-by-trapping-int/115227/1 "2007-09-22T01:06:04Z")

</div>

I’m trying to break a loop whenever CTRL-C is pressed, and find that  
this doesn’t work:

```
trap 'INT', proc {break}; count=0; while count < 10;
puts count += 1; sleep 1; end

```

I’m guessing it’s because the loop is somehow out of scope, but I’m not  
sure why.

Some minor syntax changes to trap makes it work, sort of. If I use:

```
trap('INT') {break}

```

instead, then I get a LocalJumpError. So, why does the syntax only work  
one way, and what is the right way to trap the interrupt?

---

<div class="post-metadata">

**Author:** ![Todd\_ASJacobs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/f17d59/32.png) [@Todd\_ASJacobs](https://www.ruby-forum.com/u/Todd_ASJacobs)\
**Post date:** [September 22, 2007, 2:56am UTC](https://www.ruby-forum.com/t/break-loop-by-trapping-int/115227/2 "2007-09-22T02:56:11Z")

</div>

On Sep 21, 2007, at 7:04 PM, Todd A. Jacobs wrote:

> Some minor syntax changes to trap makes it work, sort of. If I use:
> 
> ```
> trap('INT') {break}
> 
> ```
> 
> instead, then I get a LocalJumpError. So, why does the syntax only  
> work  
> one way, and what is the right way to trap the interrupt?

When the trap is triggered, the trap’s proc object receives a ‘call’  
message. This happens in the scope of top level, not in the scope of  
the while block. To get the result you want, you need to invoke a non-  
local jump mechanism. This can be done with catch and throw.

`
trap('INT') { puts "done"; throw :quit }
count = 0
catch :quit do
while count < 10;
puts count += 1
sleep 1
end
end
`

Regards, Morton

---

<div class="post-metadata">

**Author:** ![Todd\_ASJacobs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/f17d59/32.png) [@Todd\_ASJacobs](https://www.ruby-forum.com/u/Todd_ASJacobs)\
**Post date:** [September 22, 2007, 4:12am UTC](https://www.ruby-forum.com/t/break-loop-by-trapping-int/115227/3 "2007-09-22T04:12:54Z")

</div>

Morton G. wrote:

> When the trap is triggered, the trap’s proc object receives a ‘call’  
> message. This happens in the scope of top level, not in the scope of  
> the while block. To get the result you want, you need to invoke a non-  
> local jump mechanism. This can be done with catch and throw.
> 
> trap(‘INT’) { puts “done”; throw :quit }
> 
> count = 0  
> catch :quit do  
> while count \< 10;  
> puts count += 1  
> sleep 1  
> end  
> end

Yikes! Isn’t that using catch/throw as a plain vanilla goto?

---

<div class="post-metadata">

**Author:** ![Todd\_ASJacobs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/f17d59/32.png) [@Todd\_ASJacobs](https://www.ruby-forum.com/u/Todd_ASJacobs)\
**Post date:** [September 22, 2007, 3:39pm UTC](https://www.ruby-forum.com/t/break-loop-by-trapping-int/115227/4 "2007-09-22T15:39:18Z")

</div>

On Sep 21, 2007, at 10:13 PM, 7stud – wrote:

> > catch :quit do  
> > while count \< 10;  
> > puts count += 1  
> > sleep 1  
> > end  
> > end
> 
> Yikes! Isn’t that using catch/throw as a plain vanilla goto?

Not quite. Catches have scope. Consider the following:

`
trap('INT') { puts "done"; throw :quit }
count = 0
catch :quit do
while count < 10;
catch :next do ; end
puts count += 1
sleep 1
end
end
puts “But I don’t want to quit!”
throw :next
`

That doesn’t work because catch :next is invisible to throw :next.  
Throws only search upward in the stack frames, not downward. Now this  
could be made to work with continuations. With continuations you can  
do truly shocking things.

But even if were just like a goto, so what? Using trap already  
injects non-local behavior into the script. A little catch and throw  
hardly matters afters that. And it gets the job done. In this  
particular case, because there is nothing to do after the while  
block, the OP could use:

`
trap('INT') { puts "done"; exit }
count = 0
while count < 10;
puts count += 1
sleep 1
end
`

But that’s not really very different, only less general.

Regards, Morton
