| Author: Maks Orlovich <morlovich@google.com> |
| Description: Prevent crashes at startup with dynamically linked protobuf |
| |
| --- a/src/net/instaweb/rewriter/process_context.cc |
| +++ b/src/net/instaweb/rewriter/process_context.cc |
| @@ -62,10 +62,10 @@ |
| // starting up. |
| ShutDownCommandLineFlags(); |
| |
| - // The protobuf shutdown infrastructure is lazily initialized in a threadsafe |
| - // manner. See third_party/protobuf/src/google/protobuf/stubs/common.cc, |
| - // function InitShutdownFunctionsOnce. |
| +#if 0 |
| + // See comments in ApacheProcessContext ctor for why we can't use this here. |
| google::protobuf::ShutdownProtobufLibrary(); |
| +#endif |
| |
| url::Shutdown(); |
| HtmlKeywords::ShutDown(); |
| --- a/src/net/instaweb/mod_pagespeed.gyp |
| +++ b/src/net/instaweb/mod_pagespeed.gyp |
| @@ -29,6 +29,9 @@ |
| 'dependencies+': [ |
| '<(DEPTH)/third_party/httpd/httpd.gyp:include', |
| ], |
| + 'libraries': [ |
| + '-ldl', |
| + ], |
| }, |
| { |
| 'target_name': 'mod_pagespeed_ap24', |
| --- a/src/pagespeed/apache/mod_instaweb.cc |
| +++ b/src/pagespeed/apache/mod_instaweb.cc |
| @@ -19,6 +19,7 @@ |
| // that mod_pagespeed needs to do to be an Apache module. |
| |
| #include <unistd.h> |
| +#include <dlfcn.h> |
| |
| #include <cerrno> |
| #include <cstddef> |
| @@ -304,6 +305,27 @@ |
| class ApacheProcessContext { |
| public: |
| ApacheProcessContext() : apache_cmds_(NULL) { |
| + // One of our dependencies is Protocol Buffers. Dynamically linking |
| + // to them causes a problem if the following sequence of steps happens: |
| + // |
| + // 1) unload mod_pagespeed.so |
| + // 2) libprotobuf.so sticks around. |
| + // 3) load mod_pagespeed.so again |
| + // |
| + // When that occurs, a lot of global state ends up being out of sync |
| + // between the two .so's regardless of what we do. |
| + // |
| + // Oh, and w/o this patch, this happens at server startup. Steps 1 and 3 |
| + // happen because this is just how Apache + apr work. Step 2 is because it |
| + // turns out that libprotobuf triggers something called STB_GNU_UNIQUE, |
| + // which, among other things, prevents the library from being unloaded. |
| + // (Even if that wasn't there, another client could potentially keep |
| + // libprotobuf.so around just via refcount). |
| + // |
| + // The result being, we can't let ourselves be unloaded... so this asks |
| + // the dynamic linker to bump the refcount... and sadly hardcodes our path. |
| + dlopen("/usr/lib/apache2/modules/mod_pagespeed.so", RTLD_GLOBAL | RTLD_NOW); |
| + |
| ApacheRewriteDriverFactory::Initialize(); |
| InstallCommands(); |
| } |