title: ruby - IO.popen not working lame stdin and stdout encoding
body: <p>I've been working with pipes and <code>IO.popen</code> specifically in Ruby and have come across a problem that I can't figure out. I am trying to write binary data from the <code>flac</code> process to the <code>lame</code> process into a file. The code structure I am using is below.</p>
  
  <pre class="lang-ruby prettyprint-override"><code># file paths
  file = Pathname.new('example.flac').realpath
  dest = Pathname.new('example.mp3')
  
  # execute the process and return the IO object
  wav = IO.popen("flac --decode --stdout \"#{file}\"", 'rb')
  lame = IO.popen("lame -V0 --vbr-new - -", 'r+b')
  
  # write output from wav to the lame IO object
  lame &lt;&lt; wav.read
  
  # close pipe for writing (should indicate to the
  # process that input for stdin is finished).
  lame.close_write
  
  # open up destiniation file and write from lame stdout
  dest.open('wb'){|out|
      out &lt;&lt; lame.read
  }
  
  # close all pipes
  wav.close
  lame.close
  </code></pre>
  
  <p>However, it doesn't work. After <code>flac</code> has run, the script hangs and <code>lame</code> remains idle (no processor usage at all). <em>No errors or exceptions occur</em>.</p>
  
  <p>I am using cygwin on Windows 7, with the cygwin ruby package (<em>1.9.3p429 (2013-05-15) [i386-cygwin]</em>).</p>
  
  <p>I must be doing something wrong, any help is much appreciated. Thanks!</p>
  
  <p><strong>EXTRA #1</strong></p>
  
  <p>I am wanting to pipe in and out the binary data from the <code>lame</code> process because I am trying to create a platform independent (<em>ruby support limited of course</em>) to transcode audio files, and the Windows binary of <code>lame</code> only supports Windows' path names, and not cygwin's.</p>
  
  <p><strong>EDIT #1</strong></p>
  
  <p>I read in some places (I did not save the URLs, I'll try looking for them in my browser history) that <code>IO.popen</code> has known issues with blocking processes in Windows and that this could be the case.</p>
  
  <p>I have played around with other libraries including Ruby's <code>Open3.popen3</code> and <code>Open4</code>, however following a very similar code structure to the one above, the <code>lame</code> process still hangs and remains unresponsive.</p>
  
  <p><strong>EDIT #2</strong></p>
  
  <p>I found <a href="http://x-aeon.com/wp/2011/12/15/failure-at-piloting-external-processes-stdin-and-stdout-using-ruby-on-windows/" rel="nofollow noreferrer">this</a> article which talked about the limitations of of Windows's <code>cmd.exe</code> and how it prevents the use of streamed data from files to stdin.</p>
  
  <p>I refactored my code to look like shown below to test this out, and as it turns out, <code>lame</code> freezes on stdin write. If I removed (comment out) that line, the <code>lame</code> process executes (<em>with an 'unsupported audio format' warning</em>). Perhaps what the article said could explain my problem here.</p>
  
  <pre class="lang-ruby prettyprint-override"><code># file paths
  file = Pathname.new('example.flac').realpath
  dest = Pathname.new('example.mp3')
  
  # some local variables
  read_wav = nil
  read_lame = nil
  
  # the flac process, which exits succesfully
  IO.popen("flac --decode --stdout \"#{file}\"", 'rb'){|wav|
      until wav.eof do
          read_wav = wav.read
      end
  }
  
  # the lame process, which fails
  IO.popen("lame -V0 --vbr-new --verbose - -", 'r+b'){|lame|
      lame &lt;&lt; read_wav # if I comment out this, the process exits, instead of hanging
      lame.close_write
      until lame.eof do
          read_lame &lt;&lt; lame.read
      end
  }
  </code></pre>
  
  <p><strong>EDIT #3</strong></p>
  
  <p>I found this <a href="https://stackoverflow.com/questions/9796258/how-do-i-block-on-reading-a-named-pipe-in-ruby">stackoverflow</a> which (in the first answer) mentioned that <code>cygwin</code> pipe implementation is unreliable. This could perhaps not actually be related to Windows (at least not directly) but instead to cygwin and its emulation. I have instead opted to use the following code, based upon <strong>icy</strong>'s answer, <em>which works</em>!</p>
  
  <pre class="lang-ruby prettyprint-override"><code>flac = "flac --decode --stdout \"#{file}\""
  lame = "lame -V0 --vbr-new --verbose - \"#{dest}\""
  
  system(flac + ' | ' + lame)
  </code></pre>