about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-01-14 09:07:57 +0000
committerEric Wong <normalperson@yhbt.net>2011-01-14 09:07:57 +0000
commitcc43cfbb418ab7b4b2786123d33ede23b3cb5ea3 (patch)
treef13ea8da377c8a95e2c860f7ca9307807dcab6de
parent6cc7e96f972d9a648bef9d49ca245282250a5502 (diff)
downloadclogger-cc43cfbb418ab7b4b2786123d33ede23b3cb5ea3.tar.gz
This should also detect cases where CLOCK_MONOTONIC is
available at build but not at runtime.
-rw-r--r--ext/clogger_ext/broken_system_compat.h17
-rw-r--r--ext/clogger_ext/clogger.c38
-rw-r--r--ext/clogger_ext/extconf.rb5
3 files changed, 48 insertions, 12 deletions
diff --git a/ext/clogger_ext/broken_system_compat.h b/ext/clogger_ext/broken_system_compat.h
index f58307e..ec635b1 100644
--- a/ext/clogger_ext/broken_system_compat.h
+++ b/ext/clogger_ext/broken_system_compat.h
@@ -3,11 +3,15 @@
  * without clock_gettime() or CLOCK_MONOTONIC
  */
 
+#ifndef HAVE_TYPE_CLOCKID_T
+typedef clockid_t int;
+#endif
+
 #ifndef HAVE_CLOCK_GETTIME
 #  ifndef CLOCK_REALTIME
 #    define CLOCK_REALTIME 0 /* whatever */
 #  endif
-static int fake_clock_gettime(int clk_id, struct timespec *res)
+static int fake_clock_gettime(clockid_t clk_id, struct timespec *res)
 {
         struct timeval tv;
         int r = gettimeofday(&tv, NULL);
@@ -21,7 +25,12 @@ static int fake_clock_gettime(int clk_id, struct timespec *res)
 #  define clock_gettime fake_clock_gettime
 #endif /* broken systems w/o clock_gettime() */
 
-/* UGH */
-#ifndef _POSIX_MONOTONIC_CLOCK
-#  define CLOCK_MONOTONIC CLOCK_REALTIME
+/*
+ * UGH
+ * CLOCK_MONOTONIC is not guaranteed to be a macro, either
+ */
+#ifndef CLOCK_MONOTONIC
+#  if (!defined(_POSIX_MONOTONIC_CLOCK) || !defined(HAVE_CLOCK_MONOTONIC))
+#    define CLOCK_MONOTONIC CLOCK_REALTIME
+#  endif
 #endif
diff --git a/ext/clogger_ext/clogger.c b/ext/clogger_ext/clogger.c
index 7e01e6d..604b9b6 100644
--- a/ext/clogger_ext/clogger.c
+++ b/ext/clogger_ext/clogger.c
@@ -13,11 +13,38 @@
 #ifdef HAVE_FCNTL_H
 #  include <fcntl.h>
 #endif
-#define _POSIX_C_SOURCE 200112L
+#ifndef _POSIX_C_SOURCE
+#  define _POSIX_C_SOURCE 200112L
+#endif
 #include <time.h>
 #include "ruby_1_9_compat.h"
 #include "broken_system_compat.h"
 
+/*
+ * Availability of a monotonic clock needs to be detected at runtime
+ * since we could've been built on a different system than we're run
+ * under.
+ */
+static clockid_t hopefully_CLOCK_MONOTONIC = CLOCK_MONOTONIC;
+
+static void check_clock(void)
+{
+        struct timespec now;
+
+        /* we can't check this reliably at compile time */
+        if (clock_gettime(CLOCK_MONOTONIC, &now) == 0)
+                return;
+
+        if (clock_gettime(CLOCK_REALTIME, &now) == 0) {
+                hopefully_CLOCK_MONOTONIC = CLOCK_REALTIME;
+                rb_warn("CLOCK_MONOTONIC not available, "
+                        "falling back to CLOCK_REALTIME");
+        }
+        rb_warn("clock_gettime() totally broken, " \
+                "falling back to pure Ruby Clogger");
+        rb_raise(rb_eLoadError, "clock_gettime() broken");
+}
+
 static void clock_diff(struct timespec *a, const struct timespec *b)
 {
         a->tv_sec -= b->tv_sec;
@@ -346,11 +373,8 @@ static void append_ts(struct clogger *c, const VALUE *op, struct timespec *ts)
 static void append_request_time_fmt(struct clogger *c, const VALUE *op)
 {
         struct timespec now;
-        int r = clock_gettime(CLOCK_MONOTONIC, &now);
-
-        if (unlikely(r != 0))
-                rb_sys_fail("clock_gettime(CLOCK_MONONTONIC)");
 
+        clock_gettime(hopefully_CLOCK_MONOTONIC, &now);
         clock_diff(&now, &c->ts_start);
         append_ts(c, op, &now);
 }
@@ -724,7 +748,7 @@ static VALUE ccall(struct clogger *c, VALUE env)
 {
         VALUE rv;
 
-        clock_gettime(CLOCK_MONOTONIC, &c->ts_start);
+        clock_gettime(hopefully_CLOCK_MONOTONIC, &c->ts_start);
         c->env = env;
         c->cookies = Qfalse;
         rv = rb_funcall(c->app, call_id, 1, env);
@@ -859,6 +883,8 @@ void Init_clogger_ext(void)
 {
         VALUE tmp;
 
+        check_clock();
+
         ltlt_id = rb_intern("<<");
         call_id = rb_intern("call");
         each_id = rb_intern("each");
diff --git a/ext/clogger_ext/extconf.rb b/ext/clogger_ext/extconf.rb
index d87d8c2..85f2d30 100644
--- a/ext/clogger_ext/extconf.rb
+++ b/ext/clogger_ext/extconf.rb
@@ -13,10 +13,11 @@ begin
     have_macro('O_NONBLOCK', %w(unistd.h fcntl.h))
   end
 
-  unless have_macro('CLOCK_MONOTONIC', 'time.h', '-D_POSIX_C_SOURCE=200112L')
-    $CPPFLAGS += '-D_POSIX_SOURCE_200112L'
+  $CPPFLAGS += '-D_POSIX_C_SOURCE=200112L'
+  unless have_macro('CLOCK_MONOTONIC', 'time.h')
     have_func('CLOCK_MONOTONIC', 'time.h')
   end
+  have_type('clockid_t', 'time.h')
   have_func('clock_gettime', 'time.h')
   have_func('localtime_r', 'time.h') or raise "localtime_r needed"
   have_func('gmtime_r', 'time.h') or raise "gmtime_r needed"