Index: chrome/browser/zygote_main_linux.cc |
diff --git a/chrome/browser/zygote_main_linux.cc b/chrome/browser/zygote_main_linux.cc |
index 2592209b4b9f9d7131e47702fb907e25a65ccebe..c050a89341340958704b311a6742a8cfd5f8c450 100644 |
--- a/chrome/browser/zygote_main_linux.cc |
+++ b/chrome/browser/zygote_main_linux.cc |
@@ -281,6 +281,17 @@ static bool g_am_zygote_or_renderer = false; |
// We also considered patching the function in place, but this would again by |
// platform specific and the above technique seems to work well enough. |
+static void WarnOnceAboutBrokenDlsym() { |
Evan Martin
2009/09/08 22:26:16
comment above this? based on where you put it, yo
agl
2009/09/08 22:30:06
Good point. I'll move the function now and comment
|
+ static bool have_shown_warning = false; |
+ if (!have_shown_warning) { |
+ LOG(ERROR) << "Your system is broken: dlsym doesn't work! This has been " |
+ "reported to be caused by Nvidia's libGL. You should expect " |
+ "time related functions to misbehave. " |
+ "http://code.google.com/p/chromium/issues/detail?id=16800"; |
+ have_shown_warning = true; |
+ } |
+} |
+ |
struct tm* localtime(const time_t* timep) { |
if (g_am_zygote_or_renderer) { |
static struct tm time_struct; |
@@ -291,8 +302,22 @@ struct tm* localtime(const time_t* timep) { |
} else { |
typedef struct tm* (*LocaltimeFunction)(const time_t* timep); |
static LocaltimeFunction libc_localtime; |
- if (!libc_localtime) |
+ static bool have_libc_localtime = false; |
+ if (!have_libc_localtime) { |
libc_localtime = (LocaltimeFunction) dlsym(RTLD_NEXT, "localtime"); |
+ have_libc_localtime = true; |
+ } |
+ |
+ if (!libc_localtime) { |
+ // http://code.google.com/p/chromium/issues/detail?id=16800 |
+ // |
+ // Nvidia's libGL.so overrides dlsym for an unknown reason and replaces |
+ // it with a version which doesn't work. In this case we'll get a NULL |
+ // result. There's not a lot we can do at this point, so we just bodge it! |
+ WarnOnceAboutBrokenDlsym(); |
+ |
+ return gmtime(timep); |
+ } |
return libc_localtime(timep); |
} |
@@ -306,8 +331,18 @@ struct tm* localtime_r(const time_t* timep, struct tm* result) { |
typedef struct tm* (*LocaltimeRFunction)(const time_t* timep, |
struct tm* result); |
static LocaltimeRFunction libc_localtime_r; |
- if (!libc_localtime_r) |
+ static bool have_libc_localtime_r = false; |
+ if (!have_libc_localtime_r) { |
libc_localtime_r = (LocaltimeRFunction) dlsym(RTLD_NEXT, "localtime_r"); |
+ have_libc_localtime_r = true; |
+ } |
+ |
+ if (!libc_localtime_r) { |
+ // See |localtime|, above. |
+ WarnOnceAboutBrokenDlsym(); |
+ |
+ return gmtime_r(timep, result); |
+ } |
return libc_localtime_r(timep, result); |
} |