catch and display errors in initialization code
Stefan Bund [Fri, 14 Jun 2013 19:47:27 +0000 (21:47 +0200)]
PythonPublisher.cc
PythonPublisher.hh
main.cc

index f84b8da..f1699d4 100644 (file)
@@ -433,6 +433,16 @@ namespace {
         return pykit::Viewer::instance()->page()->history()->canGoForward();
     }
 
+    class ErrorCatcher
+    {
+    public:
+        explicit ErrorCatcher(std::string & out) : out_ (out) {}
+        void write(std::string const & msg)
+            { std::cerr << "append: " << msg; out_ += msg; }
+    private:
+        std::string & out_;
+    };
+
 }
 
 BOOST_PYTHON_MODULE(_pykit)
@@ -454,6 +464,10 @@ BOOST_PYTHON_MODULE(_pykit)
         .def("publish", py::pure_virtual(&pykit::Publisher::publish))
         ;
 
+    py::class_<ErrorCatcher>("ErrorCatcher", py::no_init)
+        .def("write", &ErrorCatcher::write)
+        ;
+
     py::def("openUrl", &QDesktopServices::openUrl);
 
     py::def("canGoBack", &canGoBack);
@@ -465,18 +479,28 @@ PYTHON_EXTERN_MODULE(_httpapi);
 prefix_ pykit::PythonPublisher::PythonPublisher()
     : impl_ (new Impl)
 {
+    std::string pyError;
     try {
         PYTHON_PREPARE_IMPORT(_pykit);
         PYTHON_PREPARE_IMPORT(_qt);
         PYTHON_PREPARE_IMPORT(_httpapi);
         Py_Initialize();
-        py::object initModule = py::import("init");
+
+        py::import("_pykit");
+        py::object sysModule (py::import("sys"));
+        py::object origStderr (sysModule.attr("stderr"));
+        ErrorCatcher catcher (pyError);
+        sysModule.attr("stderr") = catcher;
+
+        py::object initModule (py::import("init"));
         impl_->mainNamespace = py::extract<py::dict>(initModule.attr("__dict__"));
         impl_->pythonPublisher = py::extract<Publisher*>(impl_->mainNamespace["initialize"]());
+
+        sysModule.attr("stderr") = origStderr;
     }
     catch (boost::python::error_already_set & ex) {
         PyErr_Print();
-        throw;
+        throw PythonError(pyError);
     }
 }
 
@@ -495,6 +519,7 @@ prefix_ void pykit::PythonPublisher::publish(Request & request)
     }
     catch (py::error_already_set & ex) {
         PyErr_Print();
+        PyErr_Clear();
     }
 }
 
index 1065a38..3238cac 100644 (file)
 
 namespace pykit {
 
+    class PythonError
+        : public std::exception
+    {
+    public:
+        virtual char const * what() const throw() { return message.c_str(); }
+        std::string message;
+        PythonError(std::string message_) : message (message_) {}
+        virtual ~PythonError() throw() {}
+    };
+
     class PythonPublisher
         : public Publisher
     {
diff --git a/main.cc b/main.cc
index c4d4910..52a540d 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -19,6 +19,7 @@
 #include <QFileInfo>
 #include <QFontDatabase>
 #include <QWebSettings>
+#include <QMessageBox>
 #include <boost/scoped_ptr.hpp>
 #include "MainWindow.hh"
 #include "PythonPublisher.hh"
@@ -37,13 +38,25 @@ namespace {
             return QSize();
         return QSize(coords[0].toInt(), coords[1].toInt());
     }
+
+    void showPlatformError(char const * reason)
+    {
+        QMessageBox msgBox;
+        msgBox.setText("Es ist ein interner Fehler bei der Initialisierung"
+                       " aufgetreten. Bitte notieren sie die folgende"
+                       " Fehlermeldung und weden sie sich an den technischen"
+                       " Support.");
+        msgBox.setDetailedText(reason);
+        msgBox.setInformativeText(QString("%1 wird beendet.").arg(QApplication::applicationName()));
+        msgBox.setWindowTitle(QApplication::applicationName());
+        msgBox.exec();
+    }
 }
 
 int main(int argc, char *argv[])
 {
+    QApplication app (argc, argv);
     try {
-        QApplication app (argc, argv);
-
         QSettings settings ("pykit.ini", QSettings::IniFormat);
         QStringList arguments (app.arguments());
         settings.beginGroup("AppData");
@@ -110,9 +123,15 @@ int main(int argc, char *argv[])
 
         return app.exec();
     }
-    catch (std::exception & ex) {
+    catch (std::exception const & ex) {
         std::cerr << "Exception:\n" << ex.what() << "\n";
-        throw;
+        showPlatformError(ex.what());
+        return 1;
+    }
+    catch (...) {
+        std::cerr << "Exception: <undefined>\n";
+        showPlatformError("undefined error condition");
+        return 1;
     }
 }