From: Joel VanderWerf Date: 2009-07-15T05:29:52+09:00 Subject: Re: Process.fork weirdness Gary Wright wrote: >> But wait... Net:HTTP uses BufferedIO#writeline on sockets. That class >> doesn't itself buffer writes (only reads), but it is defined in terms >> of IO#write, which is buffered, isn't it? > > Ruby marks IO objects associated with sockets as 'synchronized' (i.e. > unbuffered). Good to know, thanks. I always just used send/recv to be sure, but now I know that's not necessary. There really don't seem to be many cases in which fork is going to cause buffer corruption, then, which explains why the issue doesn't come up much. We can rule out the cases of sockets (sync=true), log files (sync=true), most binary data files (syswrite), and pipes (usually a good idea to set sync=true, AFAIK). That leaves batch filtering of files, which is most often performed on stdin/stdout, and these descriptors are flushed in ruby's #fork wrapper. It's a real joy to retrace the steps of ruby developers, and realize how many wise decisions they made. One thing left to watch out for is race conditions in (for example): File.open(..., "w") do |f| YAML.dump(..., f) ### before the file is closed, suppose another thread forks and exits end This example shows it in action: require 'yaml' a = [1,2,3] th = Thread.new do File.open("/tmp/foo.yml", "w") do |f| YAML.dump a, f sleep 3 end end fork do sleep 1 end th.join The result is the foo.yml has two concatenated copies of the correct yaml string. This doesn't happen with Marshal.dump. Probably since it is core ruby, this possibility was anticipated. Though I don't see in marshal.c where fflush is called, and sync is false after the #dump. -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407