about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-09-03 09:20:42 -0700
committerEric Wong <normalperson@yhbt.net>2009-09-03 09:20:42 -0700
commitb7c6846e317b0f2bfe4807aab34524c2a633947c (patch)
tree013a4590fada5dd821b5f85a376d54ffda7897b8
parentafaa8efb31094a831a68b383523f9bac46a244ac (diff)
downloadclogger-b7c6846e317b0f2bfe4807aab34524c2a633947c.tar.gz
Userspace buffering defaults are dangerous as the Ruby default
IO objects do not do line-aware buffering.  This makes the
README examples with File.open much safer to use out-of-the-box
for users of the pure-Ruby version.  For users on the MRI C
extension logging to regular files, this should not have any
effect as we've optimized those to do unbuffered write(2)
syscalls anyways.
-rw-r--r--ext/clogger_ext/clogger.c9
-rw-r--r--lib/clogger/pure.rb1
-rw-r--r--test/test_clogger.rb19
3 files changed, 28 insertions, 1 deletions
diff --git a/ext/clogger_ext/clogger.c b/ext/clogger_ext/clogger.c
index 2dc1ddc..de58a9e 100644
--- a/ext/clogger_ext/clogger.c
+++ b/ext/clogger_ext/clogger.c
@@ -287,6 +287,11 @@ static VALUE obj_fileno(VALUE obj)
         return rb_funcall(obj, rb_intern("fileno"), 0);
 }
 
+static VALUE obj_enable_sync(VALUE obj)
+{
+        return rb_funcall(obj, rb_intern("sync="), 1, Qtrue);
+}
+
 /* only for writing to regular files, not stupid crap like NFS  */
 static void write_full(int fd, const void *buf, size_t count)
 {
@@ -658,8 +663,10 @@ static VALUE clogger_init(int argc, VALUE *argv, VALUE self)
                 VALUE tmp;
 
                 c->logger = rb_hash_aref(o, ID2SYM(rb_intern("logger")));
-                if (!NIL_P(c->logger))
+                if (!NIL_P(c->logger)) {
+                        rb_rescue(obj_enable_sync, c->logger, 0, 0);
                         c->fd = raw_fd(rb_rescue(obj_fileno, c->logger, 0, 0));
+                }
 
                 tmp = rb_hash_aref(o, ID2SYM(rb_intern("format")));
                 if (!NIL_P(tmp))
diff --git a/lib/clogger/pure.rb b/lib/clogger/pure.rb
index d8752b3..57e727b 100644
--- a/lib/clogger/pure.rb
+++ b/lib/clogger/pure.rb
@@ -8,6 +8,7 @@ class Clogger
   def initialize(app, opts = {})
     @app = app
     @logger = opts[:logger]
+    (@logger.sync = true) rescue nil
     @fmt_ops = compile_format(opts[:format] || Format::Common)
     @wrap_body = need_wrap_body?(@fmt_ops)
     @reentrant = nil
diff --git a/test/test_clogger.rb b/test/test_clogger.rb
index 8e6604e..d3e315e 100644
--- a/test/test_clogger.rb
+++ b/test/test_clogger.rb
@@ -434,4 +434,23 @@ class TestClogger < Test::Unit::TestCase
     assert_equal "text/plain\n", str.string
   end
 
+  def test_clogger_synced
+    io = StringIO.new
+    logger = Struct.new(:sync, :io).new(false, io)
+    assert ! logger.sync
+    def logger.<<(str)
+      io << str
+    end
+    app = lambda { |env| [302, [ %w(a) ], []] }
+    cl = Clogger.new(app, :logger => logger)
+    assert logger.sync
+  end
+
+  def test_clogger_unsyncable
+    logger = ''
+    assert ! logger.respond_to?('sync=')
+    app = lambda { |env| [302, [ %w(a) ], []] }
+    assert_nothing_raised { Clogger.new(app, :logger => logger) }
+  end
+
 end