librelist archives

« back to archive

[PATCH] attempt to support broken/crazy systems

[PATCH] attempt to support broken/crazy systems

From:
Eric Wong
Date:
2011-01-13 @ 00:37
I've just pushed this out to git://git.bogomips.org/clogger.git

If you're using a crazy, non-Free OS[1] favored by many Rubyists,
please tell me if it works or not with this patch.

[1] - I don't and will never endorse non-Free Software nor any
      for-profit organizations in my Free Software works.

From 6cc7e96f972d9a648bef9d49ca245282250a5502 Mon Sep 17 00:00:00 2001
From: Eric Wong <normalperson@yhbt.net>
Date: Wed, 12 Jan 2011 16:24:23 -0800
Subject: [PATCH] attempt to support broken/crazy systems

clock_gettime() is not available on some systems and/or
CLOCK_MONOTONIC.  This is totally broken considering the
POSIX standard was 10 years ago, now.

Nothing in gnulib, either, wtf?!
 http://www.gnu.org/software/gnulib/manual/html_node/clock_005fgettime.html
---
 ext/clogger_ext/broken_system_compat.h |   27 +++++++++++++++++++++++++++
 ext/clogger_ext/clogger.c              |    1 +
 ext/clogger_ext/extconf.rb             |    1 +
 3 files changed, 29 insertions(+), 0 deletions(-)
 create mode 100644 ext/clogger_ext/broken_system_compat.h

diff --git a/ext/clogger_ext/broken_system_compat.h 
b/ext/clogger_ext/broken_system_compat.h
new file mode 100644
index 0000000..f58307e
--- /dev/null
+++ b/ext/clogger_ext/broken_system_compat.h
@@ -0,0 +1,27 @@
+/*
+ * this header includes functions to support broken systems
+ * without clock_gettime() or CLOCK_MONOTONIC
+ */
+
+#ifndef HAVE_CLOCK_GETTIME
+#  ifndef CLOCK_REALTIME
+#    define CLOCK_REALTIME 0 /* whatever */
+#  endif
+static int fake_clock_gettime(int clk_id, struct timespec *res)
+{
+	struct timeval tv;
+	int r = gettimeofday(&tv, NULL);
+
+	assert(0 == r && "gettimeofday() broke!?");
+	res->tv_sec = tv.tv_sec;
+	res->tv_nsec = tv.tv_usec * 1000;
+
+	return r;
+}
+#  define clock_gettime fake_clock_gettime
+#endif /* broken systems w/o clock_gettime() */
+
+/* UGH */
+#ifndef _POSIX_MONOTONIC_CLOCK
+#  define CLOCK_MONOTONIC CLOCK_REALTIME
+#endif
diff --git a/ext/clogger_ext/clogger.c b/ext/clogger_ext/clogger.c
index 9703f69..7e01e6d 100644
--- a/ext/clogger_ext/clogger.c
+++ b/ext/clogger_ext/clogger.c
@@ -16,6 +16,7 @@
 #define _POSIX_C_SOURCE 200112L
 #include <time.h>
 #include "ruby_1_9_compat.h"
+#include "broken_system_compat.h"
 
 static void clock_diff(struct timespec *a, const struct timespec *b)
 {
diff --git a/ext/clogger_ext/extconf.rb b/ext/clogger_ext/extconf.rb
index 60c46a7..d87d8c2 100644
--- a/ext/clogger_ext/extconf.rb
+++ b/ext/clogger_ext/extconf.rb
@@ -17,6 +17,7 @@ begin
     $CPPFLAGS += '-D_POSIX_SOURCE_200112L'
     have_func('CLOCK_MONOTONIC', 'time.h')
   end
+  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"
   have_func('rb_str_set_len', 'ruby.h')
-- 
Eric Wong

Re: [clogger] [PATCH] attempt to support broken/crazy systems

From:
Eric Wong
Date:
2011-01-14 @ 09:14
Eric Wong <normalperson@yhbt.net> wrote:
> I've just pushed this out to git://git.bogomips.org/clogger.git
> 
> If you're using a crazy, non-Free OS[1] favored by many Rubyists,
> please tell me if it works or not with this patch.
> 
> [1] - I don't and will never endorse non-Free Software nor any
>       for-profit organizations in my Free Software works.

Here's another one which should work better, let us know if it
works for you or not (and which system you're running).

From cc43cfbb418ab7b4b2786123d33ede23b3cb5ea3 Mon Sep 17 00:00:00 2001
From: Eric Wong <normalperson@yhbt.net>
Date: Fri, 14 Jan 2011 09:07:57 +0000
Subject: [PATCH] another workaround for systems with broken CLOCK_MONOTONIC

This should also detect cases where CLOCK_MONOTONIC is
available at build but not at runtime.
---
 ext/clogger_ext/broken_system_compat.h |   17 +++++++++++---
 ext/clogger_ext/clogger.c              |   38 ++++++++++++++++++++++++++-----
 ext/clogger_ext/extconf.rb             |    5 ++-
 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"
-- 
Eric Wong

[PATCH] another try to fix systems without CLOCK_MONOTONIC

From:
Eric Wong
Date:
2011-01-14 @ 17:31
Eric Wong <normalperson@yhbt.net> wrote:
> Eric Wong <normalperson@yhbt.net> wrote:
> > I've just pushed this out to git://git.bogomips.org/clogger.git
> > 
> > If you're using a crazy, non-Free OS[1] favored by many Rubyists,
> > please tell me if it works or not with this patch.
> > 
> > [1] - I don't and will never endorse non-Free Software nor any
> >       for-profit organizations in my Free Software works.
> 
> Here's another one which should work better, let us know if it
> works for you or not (and which system you're running).

Yup, it was late and I fucked up a typedef.  This also accounts for
CLOCK_MONONTIC being a function call, too.

From b48017f818e13f8c7ddb555f8fe5fa895521af7a Mon Sep 17 00:00:00 2001
From: Eric Wong <normalperson@yhbt.net>
Date: Fri, 14 Jan 2011 17:26:59 +0000
Subject: [PATCH] another try to fix systems without CLOCK_MONOTONIC

Fix a reversed typedef and also deal with the case where
CLOCK_MONOTONIC is a function call and not a constant
macro.
---
 ext/clogger_ext/broken_system_compat.h |    2 +-
 ext/clogger_ext/clogger.c              |    4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/ext/clogger_ext/broken_system_compat.h 
b/ext/clogger_ext/broken_system_compat.h
index ec635b1..632612b 100644
--- a/ext/clogger_ext/broken_system_compat.h
+++ b/ext/clogger_ext/broken_system_compat.h
@@ -4,7 +4,7 @@
  */
 
 #ifndef HAVE_TYPE_CLOCKID_T
-typedef clockid_t int;
+typedef int clockid_t;
 #endif
 
 #ifndef HAVE_CLOCK_GETTIME
diff --git a/ext/clogger_ext/clogger.c b/ext/clogger_ext/clogger.c
index 604b9b6..d96b046 100644
--- a/ext/clogger_ext/clogger.c
+++ b/ext/clogger_ext/clogger.c
@@ -25,12 +25,14 @@
  * since we could've been built on a different system than we're run
  * under.
  */
-static clockid_t hopefully_CLOCK_MONOTONIC = CLOCK_MONOTONIC;
+static clockid_t hopefully_CLOCK_MONOTONIC;
 
 static void check_clock(void)
 {
 	struct timespec now;
 
+	hopefully_CLOCK_MONOTONIC = CLOCK_MONOTONIC;
+
 	/* we can't check this reliably at compile time */
 	if (clock_gettime(CLOCK_MONOTONIC, &now) == 0)
 		return;
-- 
Eric Wong