<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Idle Hacking &#187; IPC</title>
	<atom:link href="http://www.idle-hacking.com/tag/ipc/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.idle-hacking.com</link>
	<description>Ruby, XUL/Javascript, C/C++, and more...</description>
	<lastBuildDate>Tue, 11 May 2010 02:15:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Child process keep alive: fork and CLD Signal</title>
		<link>http://www.idle-hacking.com/2007/11/child-process-keep-alive-fork-and-cld-signal/</link>
		<comments>http://www.idle-hacking.com/2007/11/child-process-keep-alive-fork-and-cld-signal/#comments</comments>
		<pubDate>Wed, 28 Nov 2007 15:06:00 +0000</pubDate>
		<dc:creator>taf2</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[IPC]]></category>
		<category><![CDATA[Merb]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Upload]]></category>

		<guid isPermaLink="false">http://www.idle-hacking.com/2007/11/child-process-keep-alive-fork-and-cld-signal/</guid>
		<description><![CDATA[The advantage of a process over a thread is when the process dies you can get a signal telling you the process died and recover. For any long running process, it&#8217;s always very important to be able to recover from unexpected disasters. In working on a server that&#8217;s tasked with receiving a lot of large [...]]]></description>
			<content:encoded><![CDATA[<p>The advantage of a process over a thread is when the process dies you can get a signal telling you the process died and recover.  For any long running process, it&#8217;s always very important to be able to recover from unexpected disasters.  In working on a server that&#8217;s tasked with receiving a lot of large files and spending a fair bit of timing processing those files, I needed to make sure if for some reason the file input I received caused my server to go down &#8211; I could quickly recover. Because, I communicate to this server via a pipe (instead of a socket), it&#8217;s not as simple to recover using something like <a href="http://tildeslash.com/monit/">monit</a>.</p>
<p>The <a href="http://www.ruby-doc.org/core/classes/Signal.html">CLD signal</a> is sent when a child process dies.  This is great! All I need to do is trap that signal and start my process backup.  My main concern with this is will I get stuck in an infinite loop, forking new processes because some condition has caused the child process to die every time, consuming all the resources on my system.</p>
<p>Here&#8217;s my solution so far:</p>
<pre lang="ruby">
class UploadServer
  def initialize(options = {})
    @upload_read, @upload_write = IO.pipe
    @start_up_threads = (options[:start_up_threads] || 2)
    @max_read = (options[:max_read] || 1024)
    @logger = (options[:logger] || Logger.new(STDOUT))
  end

  # starts up the upload server
  def start
    @pid = fork do
      initialize_server
      while( 1 )
        select
      end
    end
    Signal.trap(0) do
      # tell the child process to die
      Process.kill("TERM", @pid)
    end
    Signal.trap("CLD") do
      # something extremely unexpected happened and the child process died
      @logger.error( "It appears the upload background process has died... Attempting a restart..." )
      # make sure we kill of any residue from the child process is cleaned up e.g. avoid defunct process
      Process.wait(@pid)
      # this is all a little risky since someone could have been in the middle of an upload
      # they'll be cut off anyway since the process died...
      # close down open pipe
      @upload_write.close
      # create a new pipe
      @upload_read, @upload_write = IO.pipe
      # start it back up
      start
    end
    @logger.debug( "Upload Process started up on #{@pid}" )
    # close the read end on the main process
    @upload_read.close
    @pid
  end
</pre>
<p>The Process.wait(@pid) is very important otherwise we&#8217;re left with a lot of &lt;defunct&gt; processes.  It may also help to throttle the issue of infinite forking.  At the very least it means we&#8217;ll never get more then 1 child process per server.  The only other thing I can imagine adding is some kind of timer to help throttle in the case that the child process dies very quickly&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.idle-hacking.com/2007/11/child-process-keep-alive-fork-and-cld-signal/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IO.pipe for interprocess communication</title>
		<link>http://www.idle-hacking.com/2007/11/iopipe-for-interprocess-communication/</link>
		<comments>http://www.idle-hacking.com/2007/11/iopipe-for-interprocess-communication/#comments</comments>
		<pubDate>Tue, 20 Nov 2007 00:43:00 +0000</pubDate>
		<dc:creator>taf2</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[IPC]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.idle-hacking.com/2007/11/iopipe-for-interprocess-communication/</guid>
		<description><![CDATA[Pipes are a really simple way to send messages from one process to another. MAX_READ = 4 rd, wd = IO.pipe pid = fork do wd.close msg_buffer = "" c = 0 while( 1 ) # select on the read end of the pipe ready = IO.select( [rd], nil, nil, 1 ) if ready ready[0].each [...]]]></description>
			<content:encoded><![CDATA[<p>Pipes are a really simple way to send messages from one process to another.</p>
<pre lang="ruby">
MAX_READ = 4

rd, wd = IO.pipe

pid = fork do
  wd.close

  msg_buffer = ""
  c = 0

  while( 1 )
    # select on the read end of the pipe
    ready = IO.select( [rd], nil, nil, 1 )
    if ready
      ready[0].each do|io|
        msg_buffer << begin
          io.read_nonblock(MAX_READ)
        rescue EOFError
          puts "the pipe was unexpectidly closed??"
          exit
        rescue Object => e
          STDERR.puts "failed with" + e.message + "\n" + e.backtrace("\n")
        end

        last_is_complete = msg_buffer.match(/\n\n$/)
        messages = msg_buffer.split("\n\n")

        # the last msg is not complete
        if !last_is_complete
          msg_buffer = messages.pop
        else
          msg_buffer = "" # reset the msg_buffer we're reading everything
        end

        messages.each do|msg|
          puts msg
          c += 1
        end

        puts c

      end
    end
  end
end

rd.close

count = 10
while( count > 0 )
  wd.write( "hello\n\nhello\n\nhello\n\n" )
  wd.write( "hello\n\n" )
  wd.write( "hello\n\nhello\n\nhello\n\n" )
  wd.write( "hello\n\n" )
  wd.write( "hello\n\n" )
  sleep 0.1
  count -= 1
end
wd.close
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.idle-hacking.com/2007/11/iopipe-for-interprocess-communication/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
