diff options
| author | mo khan <mo@mokhan.ca> | 2013-08-28 07:20:13 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2013-08-28 07:20:13 -0600 |
| commit | db1191ec0e7305d684383f8974e2fa437f77ad5a (patch) | |
| tree | 5e27b197dff849d22d8e1f50eb75aa499b16bd06 /code/snippets | |
Diffstat (limited to 'code/snippets')
56 files changed, 504 insertions, 0 deletions
diff --git a/code/snippets/abort.rb b/code/snippets/abort.rb new file mode 100644 index 0000000..51ec639 --- /dev/null +++ b/code/snippets/abort.rb @@ -0,0 +1,3 @@ +# Will exit with exit code 1. +abort + diff --git a/code/snippets/abort_message.rb b/code/snippets/abort_message.rb new file mode 100644 index 0000000..131c055 --- /dev/null +++ b/code/snippets/abort_message.rb @@ -0,0 +1,4 @@ +# You can pass a message to Kernel#abort. This message will be printed +# to STDERR before the process exits. +abort "Something went horribly wrong." + diff --git a/code/snippets/abort_with_at_exit.rb b/code/snippets/abort_with_at_exit.rb new file mode 100644 index 0000000..562ca88 --- /dev/null +++ b/code/snippets/abort_with_at_exit.rb @@ -0,0 +1,4 @@ +# Kernel#at_exit blocks are invoked when using Kernel#abort. +at_exit { puts 'Last!' } +abort "Something went horribly wrong." + diff --git a/code/snippets/at_exit.rb b/code/snippets/at_exit.rb new file mode 100644 index 0000000..1705210 --- /dev/null +++ b/code/snippets/at_exit.rb @@ -0,0 +1,5 @@ +# When Kernel#exit is invoked, before exiting Ruby invokes any blocks +# defined by Kernel#at_exit. +at_exit { puts 'Last!' } +exit + diff --git a/code/snippets/babysitting_processes.rb b/code/snippets/babysitting_processes.rb new file mode 100644 index 0000000..4f039f5 --- /dev/null +++ b/code/snippets/babysitting_processes.rb @@ -0,0 +1,10 @@ +fork do + 5.times do + sleep 1 + puts "I am an orphan!" + end +end + +Process.wait +abort "Parent process died..." + diff --git a/code/snippets/bg_process.rb b/code/snippets/bg_process.rb new file mode 100644 index 0000000..b7323e8 --- /dev/null +++ b/code/snippets/bg_process.rb @@ -0,0 +1,15 @@ +message = 'Good Morning' +recipient = 'tree@mybackyard.com' + +fork do + # In this contrived example the parent process forks a child to take + # care of sending data to the stats collector. Meanwhile the parent + # process has continued on with its work of sending the actual payload. + + # The parent process doesn't want to be slowed down with this task, and + # it doesn't matter if this would fail for some reason. + StatsCollector.record message, recipient +end + +# send message to recipient + diff --git a/code/snippets/closed_fileno.rb b/code/snippets/closed_fileno.rb new file mode 100644 index 0000000..96fa439 --- /dev/null +++ b/code/snippets/closed_fileno.rb @@ -0,0 +1,4 @@ +passwd = File.open('/etc/passwd') +puts passwd.fileno +passwd.close +puts passwd.fileno diff --git a/code/snippets/cow.rb b/code/snippets/cow.rb new file mode 100644 index 0000000..f7d85d4 --- /dev/null +++ b/code/snippets/cow.rb @@ -0,0 +1,12 @@ +arr = [1,2,3] + +fork do + # At this point the child process has been initialized. + # Because of CoW the arr variable hasn't been copied yet. + arr << 4 + # The above line of code modifies the array, so a copy of + # the array will need to be made for this process before + # it can modify it. The array in the parent process remains + # unchanged. +end + diff --git a/code/snippets/cow_no_writes.rb b/code/snippets/cow_no_writes.rb new file mode 100644 index 0000000..6e93ff7 --- /dev/null +++ b/code/snippets/cow_no_writes.rb @@ -0,0 +1,10 @@ +arr = [1,2,3] + +fork do + # At this point the child process has been initialized. + # Using CoW this process doesn't need to copy the arr variable, + # since it hasn't modified any shared values it can continue reading + # from the same memory location as the parent process. + p arr +end + diff --git a/code/snippets/custom_exit_bang.rb b/code/snippets/custom_exit_bang.rb new file mode 100644 index 0000000..604b238 --- /dev/null +++ b/code/snippets/custom_exit_bang.rb @@ -0,0 +1,3 @@ +# You can still pass an exit code. +exit! 33 + diff --git a/code/snippets/custom_exit_code.rb b/code/snippets/custom_exit_code.rb new file mode 100644 index 0000000..de83030 --- /dev/null +++ b/code/snippets/custom_exit_code.rb @@ -0,0 +1,3 @@ +# You can pass a custom exit code to this method +exit 22 + diff --git a/code/snippets/daemonize.rb b/code/snippets/daemonize.rb new file mode 100644 index 0000000..473e018 --- /dev/null +++ b/code/snippets/daemonize.rb @@ -0,0 +1,14 @@ +def daemonize_app + if RUBY_VERSION < "1.9" + exit if fork + Process.setsid + exit if fork + Dir.chdir "/" + STDIN.reopen "/dev/null" + STDOUT.reopen "/dev/null", "a" + STDERR.reopen "/dev/null", "a" + else + Process.daemon + end +end + diff --git a/code/snippets/daemons_grp_eq_pid.rb b/code/snippets/daemons_grp_eq_pid.rb new file mode 100644 index 0000000..ad4e7b0 --- /dev/null +++ b/code/snippets/daemons_grp_eq_pid.rb @@ -0,0 +1,2 @@ +puts Process.getpgrp +puts Process.pid diff --git a/code/snippets/daemons_grp_inherited.rb b/code/snippets/daemons_grp_inherited.rb new file mode 100644 index 0000000..1899024 --- /dev/null +++ b/code/snippets/daemons_grp_inherited.rb @@ -0,0 +1,7 @@ +puts Process.pid +puts Process.getpgrp + +fork { + puts Process.pid + puts Process.getpgrp +}
\ No newline at end of file diff --git a/code/snippets/decorate_default_signal_behaviour.rb b/code/snippets/decorate_default_signal_behaviour.rb new file mode 100644 index 0000000..b27bb1c --- /dev/null +++ b/code/snippets/decorate_default_signal_behaviour.rb @@ -0,0 +1,6 @@ +system_handler = trap(:INT) { + puts 'about to exit!' + system_handler.call +} +sleep 5 # so that we have time to send it a signal + diff --git a/code/snippets/env_aint_a_hash.rb b/code/snippets/env_aint_a_hash.rb new file mode 100644 index 0000000..0616c50 --- /dev/null +++ b/code/snippets/env_aint_a_hash.rb @@ -0,0 +1,3 @@ +puts ENV['EDITOR'] +puts ENV.has_key?('PATH') +puts ENV.is_a?(Hash) diff --git a/code/snippets/env_launch.sh b/code/snippets/env_launch.sh new file mode 100644 index 0000000..c085eec --- /dev/null +++ b/code/snippets/env_launch.sh @@ -0,0 +1 @@ +$ MESSAGE='wing it' ruby -e "puts ENV['MESSAGE']" diff --git a/code/snippets/env_set.rb b/code/snippets/env_set.rb new file mode 100644 index 0000000..b950dab --- /dev/null +++ b/code/snippets/env_set.rb @@ -0,0 +1,4 @@ +# The same thing, with places reversed! +ENV['MESSAGE'] = 'wing it' +system "echo $MESSAGE" + diff --git a/code/snippets/exceeding_soft_rlimits.rb b/code/snippets/exceeding_soft_rlimits.rb new file mode 100644 index 0000000..4b6f2ed --- /dev/null +++ b/code/snippets/exceeding_soft_rlimits.rb @@ -0,0 +1,7 @@ +# Set the maximum number of open files to 3. We know this +# will be maxed out because the standard streams occupy +# the first three file descriptors. +Process.setrlimit(:NOFILE, 3) + +File.open('/dev/null') + diff --git a/code/snippets/exec_python.rb b/code/snippets/exec_python.rb new file mode 100644 index 0000000..b60d0b1 --- /dev/null +++ b/code/snippets/exec_python.rb @@ -0,0 +1,8 @@ +hosts = File.open('/etc/hosts') + +python_code = %Q[import os; print os.fdopen(#{hosts.fileno}).read()] + +# The hash as the last arguments maps any file descriptors that should +# stay open through the exec. +exec 'python', '-c', python_code, {hosts.fileno => hosts} + diff --git a/code/snippets/exit_0.rb b/code/snippets/exit_0.rb new file mode 100644 index 0000000..abc539b --- /dev/null +++ b/code/snippets/exit_0.rb @@ -0,0 +1,3 @@ +# This will exit the program with the success status code (0). +exit + diff --git a/code/snippets/exit_bang.rb b/code/snippets/exit_bang.rb new file mode 100644 index 0000000..49d1f61 --- /dev/null +++ b/code/snippets/exit_bang.rb @@ -0,0 +1,3 @@ +# This will exit the program with a status code 1. +exit! + diff --git a/code/snippets/exit_bang_skips_at_exit.rb b/code/snippets/exit_bang_skips_at_exit.rb new file mode 100644 index 0000000..91e7fc7 --- /dev/null +++ b/code/snippets/exit_bang_skips_at_exit.rb @@ -0,0 +1,4 @@ +# This block will never be invoked. +at_exit { puts 'Silence!' } +exit! + diff --git a/code/snippets/fileno.rb b/code/snippets/fileno.rb new file mode 100644 index 0000000..0aef6ba --- /dev/null +++ b/code/snippets/fileno.rb @@ -0,0 +1,3 @@ +passwd = File.open('/etc/passwd') +puts passwd.fileno + diff --git a/code/snippets/getrlimit.rb b/code/snippets/getrlimit.rb new file mode 100644 index 0000000..bd21159 --- /dev/null +++ b/code/snippets/getrlimit.rb @@ -0,0 +1,2 @@ +p Process.getrlimit(:NOFILE) + diff --git a/code/snippets/if_fork.rb b/code/snippets/if_fork.rb new file mode 100644 index 0000000..5d426a8 --- /dev/null +++ b/code/snippets/if_fork.rb @@ -0,0 +1,6 @@ +if fork + puts "entered the if block" +else + puts "entered the else block" +end + diff --git a/code/snippets/if_fork_pid.rb b/code/snippets/if_fork_pid.rb new file mode 100644 index 0000000..2c3c262 --- /dev/null +++ b/code/snippets/if_fork_pid.rb @@ -0,0 +1,8 @@ +puts "parent process pid is #{Process.pid}" + +if fork + puts "entered the if block from #{Process.pid}" +else + puts "entered the else block from #{Process.pid}" +end + diff --git a/code/snippets/multiple_filenos.rb b/code/snippets/multiple_filenos.rb new file mode 100644 index 0000000..aca4caf --- /dev/null +++ b/code/snippets/multiple_filenos.rb @@ -0,0 +1,13 @@ +passwd = File.open('/etc/passwd') +puts passwd.fileno + +hosts = File.open('/etc/hosts') +puts hosts.fileno + +# Close the open passwd file. The frees up its file descriptor +# number to be used by the next opened resource. +passwd.close + +null = File.open('/dev/null') +puts null.fileno + diff --git a/code/snippets/orphan_process.rb b/code/snippets/orphan_process.rb new file mode 100644 index 0000000..3b25f92 --- /dev/null +++ b/code/snippets/orphan_process.rb @@ -0,0 +1,9 @@ +fork do + 5.times do + sleep 1 + puts "I'm an orphan!" + end +end + +abort "Parent process died..." + diff --git a/code/snippets/pipe.rb b/code/snippets/pipe.rb new file mode 100644 index 0000000..f62a237 --- /dev/null +++ b/code/snippets/pipe.rb @@ -0,0 +1,2 @@ +reader, writer = IO.pipe #=> [#<IO:fd 5>, #<IO:fd 6>] + diff --git a/code/snippets/pipe_direction.rb b/code/snippets/pipe_direction.rb new file mode 100644 index 0000000..2a81c11 --- /dev/null +++ b/code/snippets/pipe_direction.rb @@ -0,0 +1,2 @@ +reader, writer = IO.pipe +reader.write("Trying to get the reader to write something") diff --git a/code/snippets/pipe_io.rb b/code/snippets/pipe_io.rb new file mode 100644 index 0000000..f2f817b --- /dev/null +++ b/code/snippets/pipe_io.rb @@ -0,0 +1,5 @@ +reader, writer = IO.pipe +writer.write("Into the pipe I go...") +writer.close +puts reader.read + diff --git a/code/snippets/pipe_sharing_with_fork.rb b/code/snippets/pipe_sharing_with_fork.rb new file mode 100644 index 0000000..038981a --- /dev/null +++ b/code/snippets/pipe_sharing_with_fork.rb @@ -0,0 +1,16 @@ +reader, writer = IO.pipe + +fork do + reader.close + + 10.times do + # heavy lifting + writer.puts "Another one bites the dust" + end +end + +writer.close +while message = reader.gets + $stdout.puts message +end + diff --git a/code/snippets/prefork.rb b/code/snippets/prefork.rb new file mode 100644 index 0000000..65b285f --- /dev/null +++ b/code/snippets/prefork.rb @@ -0,0 +1,29 @@ +require 'socket' + +# Open a socket. +socket = TCPServer.open('0.0.0.0', 8080) + +# Preload app code. +# require 'config/environment' + +# Forward any relevant signals to the child processes. +[:INT, :QUIT].each do |signal| + Signal.trap(signal) { + wpids.each { |wpid| Process.kill(signal, wpid) } + } +end + +# For keeping track of child process pids. +wpids = [] + +5.times { + wpids << fork do + loop { + connection = socket.accept + connection.puts 'Hello Readers!' + connection.close + } + end +} + +Process.waitall
\ No newline at end of file diff --git a/code/snippets/process_spawn.rb b/code/snippets/process_spawn.rb new file mode 100644 index 0000000..04f6b0f --- /dev/null +++ b/code/snippets/process_spawn.rb @@ -0,0 +1,7 @@ +# This call will start up the 'rails server' process with the +# RAILS_ENV environment variable set to 'test'. +Process.spawn({'RAILS_ENV' => 'test'}, 'rails server') + +# This call will merge STDERR with STDOUT for the duration +# of the 'ls --help' program. +Process.spawn('ls', '--zz', STDERR => STDOUT) diff --git a/code/snippets/process_spawn_waitpid.rb b/code/snippets/process_spawn_waitpid.rb new file mode 100644 index 0000000..a8b28c4 --- /dev/null +++ b/code/snippets/process_spawn_waitpid.rb @@ -0,0 +1,11 @@ +# Do it the blocking way +system 'sleep 5' + +# Do it the non-blocking way +Process.spawn 'sleep 5' + +# Do it the blocking way with Process.spawn +# Notice that it returns the pid of the child process +pid = Process.spawn 'sleep 5' +Process.waitpid(pid) + diff --git a/code/snippets/process_wait_queue.rb b/code/snippets/process_wait_queue.rb new file mode 100644 index 0000000..872f8d8 --- /dev/null +++ b/code/snippets/process_wait_queue.rb @@ -0,0 +1,18 @@ +# We create two child processes. +2.times do + fork do + # Both processes exit immediately. + abort "Finished!" + end +end + +# The parent process waits for the first process, then sleeps for 5 seconds. +# In the meantime the second child process has exited and is no +# longer running. +puts Process.wait +sleep 5 + +# The parent process asks to wait once again, and amazingly enough, the second +# process' exit information has been queued up and is returned here. +puts Process.wait + diff --git a/code/snippets/program_name.rb b/code/snippets/program_name.rb new file mode 100644 index 0000000..989af3d --- /dev/null +++ b/code/snippets/program_name.rb @@ -0,0 +1,7 @@ +puts $PROGRAM_NAME + +10.downto(1) do |num| + $PROGRAM_NAME = "Process: #{num}" + puts $PROGRAM_NAME +end + diff --git a/code/snippets/raise_exit.rb b/code/snippets/raise_exit.rb new file mode 100644 index 0000000..7344236 --- /dev/null +++ b/code/snippets/raise_exit.rb @@ -0,0 +1,2 @@ +# Similar to abort, an unhandled exception will set the exit code to 1. +raise 'hell' diff --git a/code/snippets/rlimits.rb b/code/snippets/rlimits.rb new file mode 100644 index 0000000..a391c15 --- /dev/null +++ b/code/snippets/rlimits.rb @@ -0,0 +1,12 @@ +# The maximum number of simultaneous processes +# allowed for the current user. +Process.getrlimit(:NPROC) + +# The largest size file that may be created. +Process.getrlimit(:FSIZE) + +# The maximum size of the stack segment of the +# process. +Process.getrlimit(:STACK) + + diff --git a/code/snippets/setrlimit.rb b/code/snippets/setrlimit.rb new file mode 100644 index 0000000..990ca5e --- /dev/null +++ b/code/snippets/setrlimit.rb @@ -0,0 +1,3 @@ +Process.setrlimit(:NOFILE, 4096) +p Process.getrlimit(:NOFILE) + diff --git a/code/snippets/signals_chld_naive.rb b/code/snippets/signals_chld_naive.rb new file mode 100644 index 0000000..59929fb --- /dev/null +++ b/code/snippets/signals_chld_naive.rb @@ -0,0 +1,30 @@ +child_processes = 3 +dead_processes = 0 +# We fork 3 child processes. +child_processes.times do + fork do + # They sleep for 3 seconds. + sleep 3 + end +end + +# Our parent process will be busy doing some intense mathematics. +# But still wants to know when one of its children exits. + +# By trapping the :CHLD signal our process will be notified by the kernel +# when one of its children exits. +trap(:CHLD) do + # Since Process.wait queues up any data that it has for us we can ask for it + # here, since we know that one of our child processes has exited. + + puts Process.wait + dead_processes += 1 + # We exit explicitly once all the child processes are accounted for. + exit if dead_processes == child_processes +end + +# Work it. +loop do + (Math.sqrt(rand(44)) ** 8).floor + sleep 1 +end diff --git a/code/snippets/signals_chld_nohang.rb b/code/snippets/signals_chld_nohang.rb new file mode 100644 index 0000000..621a70c --- /dev/null +++ b/code/snippets/signals_chld_nohang.rb @@ -0,0 +1,42 @@ +child_processes = 3 +dead_processes = 0 +# We fork 3 child processes. +child_processes.times do + fork do + # They sleep for 3 seconds. + sleep 3 + end +end + +# Sync $stdout so the call to #puts in the CHLD handler isn't +# buffered. Can cause a ThreadError if a signal handler is +# interrupted after calling #puts. Always a good idea to do +# this if your handlers will be doing IO. +$stdout.sync = true + +# Our parent process will be busy doing some intense mathematics. +# But still wants to know when one of its children exits. + +# By trapping the :CHLD signal our process will be notified by the kernel +# when one of its children exits. +trap(:CHLD) do + # Since Process.wait queues up any data that it has for us we can ask for it + # here, since we know that one of our child processes has exited. + + # We loop over a non-blocking Process.wait to ensure that any dead child + # processes are accounted for. + begin + while pid = Process.wait(-1, Process::WNOHANG) + puts pid + dead_processes += 1 + end + rescue Errno::ECHILD + end +end + +loop do + # We exit ourself once all the child processes are accounted for. + exit if dead_processes == child_processes + + sleep 1 +end diff --git a/code/snippets/socketpair.rb b/code/snippets/socketpair.rb new file mode 100644 index 0000000..06ae044 --- /dev/null +++ b/code/snippets/socketpair.rb @@ -0,0 +1,3 @@ +require 'socket' +Socket.pair(:UNIX, :DGRAM, 0) #=> [#<Socket:fd 15>, #<Socket:fd 16>] + diff --git a/code/snippets/socketpair_communication.rb b/code/snippets/socketpair_communication.rb new file mode 100644 index 0000000..c8e0f09 --- /dev/null +++ b/code/snippets/socketpair_communication.rb @@ -0,0 +1,26 @@ +require 'socket' + +child_socket, parent_socket = Socket.pair(:UNIX, :DGRAM, 0) +maxlen = 1000 + +fork do + parent_socket.close + + 4.times do + instruction = child_socket.recv(maxlen) + child_socket.send("#{instruction} accomplished!", 0) + end +end +child_socket.close + +2.times do + parent_socket.send("Heavy lifting", 0) +end +2.times do + parent_socket.send("Feather lifting", 0) +end + +4.times do + $stdout.puts parent_socket.recv(maxlen) +end + diff --git a/code/snippets/soft_to_hard_rlimit.rb b/code/snippets/soft_to_hard_rlimit.rb new file mode 100644 index 0000000..e6a2e11 --- /dev/null +++ b/code/snippets/soft_to_hard_rlimit.rb @@ -0,0 +1 @@ +Process.setrlimit(:NOFILE, Process.getrlimit(:NOFILE)[1]) diff --git a/code/snippets/spawn_open3_eg.rb b/code/snippets/spawn_open3_eg.rb new file mode 100644 index 0000000..0417aa0 --- /dev/null +++ b/code/snippets/spawn_open3_eg.rb @@ -0,0 +1,14 @@ +# This is available as part of the standard library. +require 'open3' + +Open3.popen3('grep', 'data') { |stdin, stdout, stderr| + stdin.puts "some\ndata" + stdin.close + puts stdout.read +} + +# Open3 will use Process.spawn when available. Options can be passed to +# Process.spawn like so: +Open3.popen3('ls', '-uhh', :err => :out) { |stdin, stdout, stderr| + puts stdout.read +} diff --git a/code/snippets/spawn_popen_block.rb b/code/snippets/spawn_popen_block.rb new file mode 100644 index 0000000..193af6a --- /dev/null +++ b/code/snippets/spawn_popen_block.rb @@ -0,0 +1,8 @@ +# An IO object is passed into the block. In this case we open the stream +# for writing, so the stream is set to the STDIN of the spawned process. +# +# If we open the stream for reading (the default) then +# the stream is set to the STDOUT of the spawned process. +IO.popen('less', 'w') { |stream| + stream.puts "some\ndata" +} diff --git a/code/snippets/spawn_popen_no_block.rb b/code/snippets/spawn_popen_no_block.rb new file mode 100644 index 0000000..9cf54a0 --- /dev/null +++ b/code/snippets/spawn_popen_no_block.rb @@ -0,0 +1,4 @@ +# This example will return a file descriptor (IO object). Reading from it +# will return what was printed to STDOUT from the shell command. +IO.popen('ls') + diff --git a/code/snippets/standard_streams.rb b/code/snippets/standard_streams.rb new file mode 100644 index 0000000..9f24fd3 --- /dev/null +++ b/code/snippets/standard_streams.rb @@ -0,0 +1,3 @@ +puts STDIN.fileno +puts STDOUT.fileno +puts STDERR.fileno diff --git a/code/snippets/trap_int_signal.rb b/code/snippets/trap_int_signal.rb new file mode 100644 index 0000000..b1d9d5b --- /dev/null +++ b/code/snippets/trap_int_signal.rb @@ -0,0 +1,8 @@ +trap(:INT) { puts 'This is the first signal handler' } + +old_handler = trap(:INT) { + old_handler.call + puts 'This is the second handler' + exit +} +sleep 5 # so that we have time to send it a signal diff --git a/code/snippets/wait2.rb b/code/snippets/wait2.rb new file mode 100644 index 0000000..329cbc7 --- /dev/null +++ b/code/snippets/wait2.rb @@ -0,0 +1,26 @@ +# We create 5 child processes. +5.times do + fork do + # Each generates a random number. If even they exit + # with a 111 exit code, otherwise they use a 112 exit code. + if rand(5).even? + exit 111 + else + exit 112 + end + end +end + +5.times do + # We wait for each of the child processes to exit. + pid, status = Process.wait2 + + # If the child process exited with the 111 exit code + # then we know they encountered an even number. + if status.exitstatus == 111 + puts "#{pid} encountered an even number!" + else + puts "#{pid} encountered an odd number!" + end +end + diff --git a/code/snippets/wait_for_each_process.rb b/code/snippets/wait_for_each_process.rb new file mode 100644 index 0000000..ca14418 --- /dev/null +++ b/code/snippets/wait_for_each_process.rb @@ -0,0 +1,14 @@ +# We create 3 child processes. +3.times do + fork do + # Each one sleeps for a random amount of number less than 5 seconds. + sleep rand(5) + end +end + +3.times do + # We wait for each child process to exit and print the pid that + # gets returned. + puts Process.wait +end + diff --git a/code/snippets/waitpid2.rb b/code/snippets/waitpid2.rb new file mode 100644 index 0000000..3a5c2f2 --- /dev/null +++ b/code/snippets/waitpid2.rb @@ -0,0 +1,11 @@ +favourite = fork do + exit 77 +end + +middle_child = fork do + abort "I want to be waited on!" +end + +pid, status = Process.waitpid2 favourite +puts status.exitstatus + diff --git a/code/snippets/zombie_process.rb b/code/snippets/zombie_process.rb new file mode 100644 index 0000000..bf2413e --- /dev/null +++ b/code/snippets/zombie_process.rb @@ -0,0 +1,17 @@ +message = 'Good Morning' +recipient = 'tree@mybackyard.com' + +pid = fork do + # In this contrived example the parent process forks a child to take + # care of sending data to the stats collector. Meanwhile the parent + # process has continued on with its work of sending the actual payload. + + # The parent process doesn't want to be slowed down with this task, and + # it doesn't matter if this would fail for some reason. + StatsCollector.record message, recipient +end + +# This line ensures that the process performing the stats collection +# won't become a zombie. +Process.detach(pid) + diff --git a/code/snippets/zombies_eg.rb b/code/snippets/zombies_eg.rb new file mode 100644 index 0000000..475c11c --- /dev/null +++ b/code/snippets/zombies_eg.rb @@ -0,0 +1,7 @@ +# Create a child process that exits after 1 second. +pid = fork { sleep 1 } +# Print its pid. +puts pid +# Put the parent process to sleep so we can inspect the +# process status of the child +sleep 5 |
