# Fork, trap and exec. Pickaxe typo?

**URL:** <https://www.ruby-forum.com/t/fork-trap-and-exec-pickaxe-typo/76730>\
**Category:** Ruby\
**Created:** [November 20, 2006, 9:12pm UTC](https://www.ruby-forum.com/t/fork-trap-and-exec-pickaxe-typo/76730 "2006-11-20T21:12:04Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jashmenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/eb9ed0/32.png) [@jashmenn](https://www.ruby-forum.com/u/jashmenn)\
**Post date:** [November 20, 2006, 9:12pm UTC](https://www.ruby-forum.com/t/fork-trap-and-exec-pickaxe-typo/76730/1 "2006-11-20T21:12:04Z")

</div>

Hey All, I got this code straight from the PickAxe:

trap(“CLD”) {  
pid = Process.wait  
puts “Child pid #{pid}: terminated”  
exit  
}

exec(“echo ‘hello world’”) if fork == nil

But it doesnt word!  
The CLD trap’ped call never executes.

Another question… If I perform the exec 4 times the trap call back  
should be called four times, right?

So this code:

trap(“CLD”) {  
pid = Process.wait  
puts “Child pid #{pid}: terminated”  
exit  
}

1.upto(4) do  
exec(“echo “hello $HOSTNAME #{Process.pid}\n” ; sleep 5”) if  
fork.nil?  
end

Should call trap(“CLD”) four times, right?

Thanks for your help in advance.

---

<div class="post-metadata">

**Author:** ![jashmenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/eb9ed0/32.png) [@jashmenn](https://www.ruby-forum.com/u/jashmenn)\
**Post date:** [November 20, 2006, 9:16pm UTC](https://www.ruby-forum.com/t/fork-trap-and-exec-pickaxe-typo/76730/2 "2006-11-20T21:16:05Z")

</div>

Another question, trap(“CLD”) should be called even with a non-zero  
exit status, correct?

FYI, I am running under MacOSX 10.4

$ ruby --version  
ruby 1.8.4 (2005-12-24) [i686-darwin8.6.1]

---

<div class="post-metadata">

**Author:** ![jashmenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/eb9ed0/32.png) [@jashmenn](https://www.ruby-forum.com/u/jashmenn)\
**Post date:** [November 20, 2006, 9:28pm UTC](https://www.ruby-forum.com/t/fork-trap-and-exec-pickaxe-typo/76730/3 "2006-11-20T21:28:09Z")

</div>

On Tue, 21 Nov 2006, Nate M. wrote:

> trap(“CLD”) {  
> pid = Process.wait  
> puts “Child pid #{pid}: terminated”  
> # exit  
> }
> 
> 1.upto(4) do  
> exec(“echo “hello $HOSTNAME #{Process.pid}\n” ; sleep 5”) if  
> fork.nil?  
> end

sleep 25

> Should call trap(“CLD”) four times, right?
> 
> Thanks for your help in advance.

that should do the job. You didn’t wait around for things to happen.  
Hugh

---

<div class="post-metadata">

**Author:** ![jashmenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/eb9ed0/32.png) [@jashmenn](https://www.ruby-forum.com/u/jashmenn)\
**Post date:** [November 20, 2006, 9:36pm UTC](https://www.ruby-forum.com/t/fork-trap-and-exec-pickaxe-typo/76730/4 "2006-11-20T21:36:11Z")

</div>

Yeah, but how do I wait for an unknown amount of time? It would seem  
that this would do it:

trap(“CLD”) {  
pid = Process.wait  
puts “Child pid #{pid}: terminated”  
}

1.upto(4) do  
fork do  
exec(“sleep 3 && echo “hello $HOSTNAME #{Process.pid}\n””)  
end  
end

Process.waitall

But trap isnt always called on all the children.

Example output:

hello nate.cpo 4136

Child pid 4136: terminated  
hello nate.cpo 4139

Child pid 4139: terminated  
hello nate.cpo 4137

hello nate.cpo 4138

Child pid 4138: terminated

Notice that 4137 never called the trap callback even though  
Process.waitall was called.

---

<div class="post-metadata">

**Author:** ![jashmenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/eb9ed0/32.png) [@jashmenn](https://www.ruby-forum.com/u/jashmenn)\
**Post date:** [November 20, 2006, 9:46pm UTC](https://www.ruby-forum.com/t/fork-trap-and-exec-pickaxe-typo/76730/5 "2006-11-20T21:46:14Z")

</div>

On Tue, 21 Nov 2006, Nate M. wrote:

> ```
> exec("sleep 3 && echo \"hello $HOSTNAME #{Process.pid}\n\"")
> 
> ```
> 
> end  
> end
> 
> Process.waitall

puts Process.waitall

## =begin ri\_output ------------------------------------------------------- Process::waitall Process.waitall =\> [[pid1,status1], …]

```
 Waits for all children, returning an array of _pid_/_status_ pairs
 (where _status_ is a +Process::Status+ object).
    [...]

```

=end

# So while I’m not sure what’s happening to the missing signal

# you should be able to see that all the processes have finished.

> But trap isnt always called on all the children.

> Example output:

```
    [...]

```

> Notice that 4137 never called the trap callback even though  
> Process.waitall was called.

```
    Hugh
```

---

<div class="post-metadata">

**Author:** ![jashmenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/eb9ed0/32.png) [@jashmenn](https://www.ruby-forum.com/u/jashmenn)\
**Post date:** [November 20, 2006, 11:10pm UTC](https://www.ruby-forum.com/t/fork-trap-and-exec-pickaxe-typo/76730/6 "2006-11-20T23:10:33Z")

</div>

What you want is SIGCHLD. s/CLD/CHLD/

-rr-

---

<div class="post-metadata">

**Author:** ![jashmenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/eb9ed0/32.png) [@jashmenn](https://www.ruby-forum.com/u/jashmenn)\
**Post date:** [November 20, 2006, 10:26pm UTC](https://www.ruby-forum.com/t/fork-trap-and-exec-pickaxe-typo/76730/7 "2006-11-20T22:26:19Z")

</div>

This is so strange. I feel that I am really missing something here.

Here is my updated code, but the output is odd:

require ‘pp’

trap(“CLD”) {  
pid = Process.wait  
puts “Child pid #{pid}: terminated”  
}

1.upto(4) do  
fork do  
exec(“sleep 3 && echo “hello $HOSTNAME #{Process.pid}\n””)  
end  
end

pp Process.waitall

== output:

hello nate.cpo 4655

Child pid 4655: terminated  
hello nate.cpo 4660

hello nate.cpo 4657

hello nate.cpo 4659

Child pid 4660: terminated  
[[4659, #\<Process::Status: pid=4659,exited(0)\>],  
[4657, #\<Process::Status: pid=4657,exited(0)\>]]

The processes that are trapped call the callback and never end up in  
Process.waitall. And those in Process.waitall never send the SIGCLD.

I think I need to do more research on this…

---

<div class="post-metadata">

**Author:** ![jashmenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/eb9ed0/32.png) [@jashmenn](https://www.ruby-forum.com/u/jashmenn)\
**Post date:** [November 21, 2006, 5:39am UTC](https://www.ruby-forum.com/t/fork-trap-and-exec-pickaxe-typo/76730/8 "2006-11-21T05:39:23Z")

</div>

On Nov 20, 2006, at 4:25 PM, Nate M. wrote:

> This is so strange. I feel that I am really missing something here.
> 
> Here is my updated code, but the output is odd:
> 
> require ‘pp’
> 
> trap(“CLD”) {  
> pid = Process.wait

I think this causes a conflict with Process.waitall below. I don’t  
understand why you’re doing this and a waitall. One thing seems  
clear: any child process whose exit is caught here won’t be caught by  
the waitall below.

> puts “Child pid #{pid}: terminated”  
> }
> 
> 1.upto(4) do  
> fork do  
> exec(“sleep 3 && echo “hello $HOSTNAME #{Process.pid}\n””)  
> end  
> end
> 
> pp Process.waitall

The following code and output may give you some ideas about what is  
happening.

`
DEBUG = []
trap(“CLD”) {
pid = Process.wait
DEBUG << “Child pid #{pid} terminated”
}
begin
4.times do
if fork.nil?
exec(%{echo “hello from child #{Process.pid}”})
else
sleep 1
end
end
ensure
DEBUG.each { |s| puts s }
end
` RubyMate r5712 running Ruby v1.8.2 (/usr/bin/ruby) hello from child 1743 hello from child 1744 hello from child 1745 hello from child 1746 Child pid 1743 terminated Child pid 1744 terminated Child pid 1745 terminated Child pid 1746 terminated

Regards, Morton

---

<div class="post-metadata">

**Author:** ![jashmenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/eb9ed0/32.png) [@jashmenn](https://www.ruby-forum.com/u/jashmenn)\
**Post date:** [November 20, 2006, 11:18pm UTC](https://www.ruby-forum.com/t/fork-trap-and-exec-pickaxe-typo/76730/9 "2006-11-20T23:18:35Z")

</div>

Apologies, that doesn’t change anything… /me should really test first

-rr-
