summaryrefslogtreecommitdiff
path: root/code/snippets
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2013-08-28 07:20:13 -0600
committermo khan <mo@mokhan.ca>2013-08-28 07:20:13 -0600
commitdb1191ec0e7305d684383f8974e2fa437f77ad5a (patch)
tree5e27b197dff849d22d8e1f50eb75aa499b16bd06 /code/snippets
initial commitHEADmaster
Diffstat (limited to 'code/snippets')
-rw-r--r--code/snippets/abort.rb3
-rw-r--r--code/snippets/abort_message.rb4
-rw-r--r--code/snippets/abort_with_at_exit.rb4
-rw-r--r--code/snippets/at_exit.rb5
-rw-r--r--code/snippets/babysitting_processes.rb10
-rw-r--r--code/snippets/bg_process.rb15
-rw-r--r--code/snippets/closed_fileno.rb4
-rw-r--r--code/snippets/cow.rb12
-rw-r--r--code/snippets/cow_no_writes.rb10
-rw-r--r--code/snippets/custom_exit_bang.rb3
-rw-r--r--code/snippets/custom_exit_code.rb3
-rw-r--r--code/snippets/daemonize.rb14
-rw-r--r--code/snippets/daemons_grp_eq_pid.rb2
-rw-r--r--code/snippets/daemons_grp_inherited.rb7
-rw-r--r--code/snippets/decorate_default_signal_behaviour.rb6
-rw-r--r--code/snippets/env_aint_a_hash.rb3
-rw-r--r--code/snippets/env_launch.sh1
-rw-r--r--code/snippets/env_set.rb4
-rw-r--r--code/snippets/exceeding_soft_rlimits.rb7
-rw-r--r--code/snippets/exec_python.rb8
-rw-r--r--code/snippets/exit_0.rb3
-rw-r--r--code/snippets/exit_bang.rb3
-rw-r--r--code/snippets/exit_bang_skips_at_exit.rb4
-rw-r--r--code/snippets/fileno.rb3
-rw-r--r--code/snippets/getrlimit.rb2
-rw-r--r--code/snippets/if_fork.rb6
-rw-r--r--code/snippets/if_fork_pid.rb8
-rw-r--r--code/snippets/multiple_filenos.rb13
-rw-r--r--code/snippets/orphan_process.rb9
-rw-r--r--code/snippets/pipe.rb2
-rw-r--r--code/snippets/pipe_direction.rb2
-rw-r--r--code/snippets/pipe_io.rb5
-rw-r--r--code/snippets/pipe_sharing_with_fork.rb16
-rw-r--r--code/snippets/prefork.rb29
-rw-r--r--code/snippets/process_spawn.rb7
-rw-r--r--code/snippets/process_spawn_waitpid.rb11
-rw-r--r--code/snippets/process_wait_queue.rb18
-rw-r--r--code/snippets/program_name.rb7
-rw-r--r--code/snippets/raise_exit.rb2
-rw-r--r--code/snippets/rlimits.rb12
-rw-r--r--code/snippets/setrlimit.rb3
-rw-r--r--code/snippets/signals_chld_naive.rb30
-rw-r--r--code/snippets/signals_chld_nohang.rb42
-rw-r--r--code/snippets/socketpair.rb3
-rw-r--r--code/snippets/socketpair_communication.rb26
-rw-r--r--code/snippets/soft_to_hard_rlimit.rb1
-rw-r--r--code/snippets/spawn_open3_eg.rb14
-rw-r--r--code/snippets/spawn_popen_block.rb8
-rw-r--r--code/snippets/spawn_popen_no_block.rb4
-rw-r--r--code/snippets/standard_streams.rb3
-rw-r--r--code/snippets/trap_int_signal.rb8
-rw-r--r--code/snippets/wait2.rb26
-rw-r--r--code/snippets/wait_for_each_process.rb14
-rw-r--r--code/snippets/waitpid2.rb11
-rw-r--r--code/snippets/zombie_process.rb17
-rw-r--r--code/snippets/zombies_eg.rb7
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