]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Instead of exiting, disable optional eCAP services that fail initialization.
authorAlex Rousskov <rousskov@measurement-factory.com>
Wed, 30 Mar 2011 18:07:38 +0000 (12:07 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Wed, 30 Mar 2011 18:07:38 +0000 (12:07 -0600)
Report all service initialization failures but mark optional services
down instead of killing Squid by propagating the failure to the Squid
core.  An initialization failure of an optional (bypass=1) service
should not lead to Squid quitting because, according to squid.conf, such
a service may be replaced by other services (using adaptation sets) or
simply ignored.

Initialization failures of essential services still lead to fatal
errors, but they are now reported better.

Ecap services should indicate failures by throwing an exception. Squid
reports exception details using std::exception::what() method if
possible.

src/adaptation/ecap/ServiceRep.cc
src/adaptation/ecap/ServiceRep.h

index 1449c41373bdcc1e9958e7266a870b23bcfca2e0..b30e37f06acb9c87ad2ab61dd1d140ff6c822c01 100644 (file)
@@ -99,17 +99,58 @@ Adaptation::Ecap::ServiceRep::finalize()
     Adaptation::Service::finalize();
     theService = FindAdapterService(cfg().uri);
     if (theService) {
-        debugs(93,2, HERE << "configuring eCAP service: " << theService->uri());
-        const ConfigRep cfgRep(dynamic_cast<const ServiceConfig&>(cfg()));
-        theService->configure(cfgRep);
-
-        debugs(93,DBG_IMPORTANT, "Starting eCAP service: " << theService->uri());
-        theService->start();
+        try {
+            tryConfigureAndStart();
+            Must(up());
+        }
+        catch (const std::exception &e) { // standardized exceptions
+            if (!handleFinalizeFailure(e.what()))
+                throw; // rethrow for upper layers to handle
+        }
+        catch (...) { // all other exceptions
+            if (!handleFinalizeFailure("unrecognized exception"))
+                throw; // rethrow for upper layers to handle
+        }
+        return; // success or handled exception
     } else {
         debugs(93,DBG_IMPORTANT, "WARNING: configured ecap_service was not loaded: " << cfg().uri);
     }
 }
 
+/// attempts to configure and start eCAP service; the caller handles exceptions
+void
+Adaptation::Ecap::ServiceRep::tryConfigureAndStart()
+{
+    debugs(93,2, HERE << "configuring eCAP service: " << theService->uri());
+    const ConfigRep cfgRep(dynamic_cast<const ServiceConfig&>(cfg()));
+    theService->configure(cfgRep);
+
+    debugs(93,DBG_IMPORTANT, "Starting eCAP service: " << theService->uri());
+    theService->start();
+}
+
+/// handles failures while configuring or starting an eCAP service;
+/// returns false if the error must be propagated to higher levels
+bool
+Adaptation::Ecap::ServiceRep::handleFinalizeFailure(const char *error)
+{
+    const bool salvage = cfg().bypass;
+    const int level = salvage ? DBG_IMPORTANT : DBG_CRITICAL;
+    const char *kind = salvage ? "optional" : "essential";
+    debugs(93, level, "ERROR: failed to start " << kind << " eCAP service: " <<
+           cfg().uri << ":\n" << error);
+
+    if (!salvage)
+        return false; // we cannot handle the problem; the caller may escalate
+
+    // make up() false, preventing new adaptation requests and enabling bypass
+    theService.reset();
+    debugs(93, level, "WARNING: " << kind << " eCAP service is " <<
+           "down after initialization failure: " << cfg().uri);
+
+   return true; // tell the caller to ignore the problem because we handled it
+}
+
 bool Adaptation::Ecap::ServiceRep::probed() const
 {
     return true; // we "probe" the adapter in finalize().
index 8e1818f0f59d674b232d5cb6c859dc34dbdecf92..b21179b97bf5fd6f391371639f6969801781903f 100644 (file)
@@ -39,6 +39,10 @@ public:
     virtual void detach();
     virtual bool detached() const;
 
+protected:
+    void tryConfigureAndStart();
+    bool handleFinalizeFailure(const char *error);
+
 private:
     AdapterService theService; // the actual adaptation service we represent
     bool           isDetached;