Browse Source

[trac983] worked around the symbol sharing issue between multiple .so's.
there doesn't seem to be a simple and portable way to allow direct sharing,
so I chose to get access to the variables via the python interpretor.

JINMEI Tatuya 14 years ago
parent
commit
f29890eed7

+ 1 - 2
src/lib/python/isc/acl/Makefile.am

@@ -10,7 +10,7 @@ pythondir = $(PYTHON_SITEPKG_DIR)/isc/acl
 pyexec_LTLIBRARIES = acl.la dns.la
 pyexecdir = $(PYTHON_SITEPKG_DIR)/isc/acl
 
-acl_la_SOURCES = acl.h acl.cc
+acl_la_SOURCES = acl.cc
 acl_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
 acl_la_LDFLAGS = $(PYTHON_LDFLAGS)
 acl_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
@@ -31,7 +31,6 @@ acl_la_LIBADD += $(PYTHON_LIB)
 
 dns_la_LDFLAGS += -module
 dns_la_LIBADD = $(top_builddir)/src/lib/acl/libdnsacl.la
-dns_la_LIBADD += acl.la
 dns_la_LIBADD += $(PYTHON_LIB)
 
 EXTRA_DIST = acl.py dns.py

+ 7 - 9
src/lib/python/isc/acl/acl.cc

@@ -18,24 +18,22 @@
 
 #include <acl/acl.h>
 
-#include "acl.h"
-
 using namespace isc::util::python;
-using namespace isc::acl::python;
 
-namespace isc {
-namespace acl {
-namespace python {
+namespace {
+// Commonly used Python exception objects.  Right now the acl module consists
+// of only one .cc file, so we hide them in an unnamed namespace.  If and when
+// we extend this module with multiple .cc files, we should move them to
+// a named namespace, say isc::acl::python, and declare them in a separate
+// header file.
 PyObject* po_ACLError;
 PyObject* po_LoaderError;
 }
-}
-}
 
 namespace {
 PyModuleDef acl = {
     { PyObject_HEAD_INIT(NULL) NULL, 0, NULL},
-    "isc.acl",
+    "isc.acl.acl",
     "This module provides Python bindings for the C++ classes in the "
     "isc::acl namespace",
     -1,

+ 0 - 35
src/lib/python/isc/acl/acl.h

@@ -1,35 +0,0 @@
-// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef __PYTHON_ACL_H
-#define __PYTHON_ACL_H 1
-
-#include <Python.h>
-
-namespace isc {
-namespace acl {
-namespace python {
-
-extern PyObject* po_ACLError;
-extern PyObject* po_LoaderError;
-
-} // namespace python
-} // namespace acl
-} // namespace isc
-
-#endif // __PYTHON_ACL_H
-
-// Local Variables:
-// mode: c++
-// End:

+ 28 - 2
src/lib/python/isc/acl/dns.cc

@@ -24,7 +24,7 @@
 #include <acl/acl.h>
 #include <acl/dns.h>
 
-#include "acl.h"
+#include "dns.h"
 #include "dns_requestcontext_python.h"
 #include "dns_requestacl_python.h"
 
@@ -53,7 +53,7 @@ loadRequestACL(PyObject*, PyObject* args) {
             }
             return (py_acl);
         } catch (const exception& ex) {
-            PyErr_SetString(isc::acl::python::po_LoaderError, ex.what());
+            PyErr_SetString(getACLException("LoaderError"), ex.what());
             return (NULL);
         } catch (...) {
             PyErr_SetString(PyExc_SystemError, "Unexpected C++ exception");
@@ -86,6 +86,32 @@ PyModuleDef dnsacl = {
 };
 } // end of unnamed namespace
 
+namespace isc {
+namespace acl {
+namespace dns {
+namespace python {
+PyObject*
+getACLException(const char* ex_name) {
+    PyObject* ex_obj = NULL;
+
+    PyObject* acl_module = PyImport_AddModule("isc.acl.acl");
+    if (acl_module != NULL) {
+        PyObject* acl_dict = PyModule_GetDict(acl_module);
+        if (acl_dict != NULL) {
+            ex_obj = PyDict_GetItemString(acl_dict, ex_name);
+        }
+    }
+
+    if (ex_obj == NULL) {
+        ex_obj = PyExc_RuntimeError;
+    }
+    return (ex_obj);
+}
+}
+}
+}
+}
+
 PyMODINIT_FUNC
 PyInit_dns(void) {
     PyObject* mod = PyModule_Create(&dnsacl);

+ 52 - 0
src/lib/python/isc/acl/dns.h

@@ -0,0 +1,52 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __PYTHON_ACL_DNS_H
+#define __PYTHON_ACL_DNS_H 1
+
+#include <Python.h>
+
+namespace isc {
+namespace acl {
+namespace dns {
+namespace python {
+
+// Return a Python exception object of the given name (ex_name) defined in
+// the isc.acl.acl loadable module.
+//
+// Since the acl module is a different binary image and is loaded separately
+// from the dns module, it would be very tricky to directly access to
+// C/C++ symbols defined in that module.  So we get access to these object
+// using the Python interpretor through this wrapper function.
+//
+// The __init__.py file should ensure isc.acl.acl has been loaded by the time
+// whenever this function is called, and there shouldn't be no operation
+// within this function that can fail (such as dynamic memory allocation),
+// so this function should always succeed.  Yet there may be an overlooked
+// failure mode, perhaps due to a bug in the binding implementation, or
+// due to invalid usage.  As a last resort for such cases, this function
+// returns PyExc_RuntimeError (a C binding of Python's RuntimeError) should
+// it encounters an unexpected failure.
+extern PyObject* getACLException(const char* ex_name);
+
+} // namespace python
+} // namespace dns
+} // namespace acl
+} // namespace isc
+
+#endif // __PYTHON_ACL_DNS_H
+
+// Local Variables:
+// mode: c++
+// End:

+ 4 - 4
src/lib/python/isc/acl/dns_requestacl_python.cc

@@ -28,14 +28,13 @@
 #include <acl/acl.h>
 #include <acl/dns.h>
 
-#include "acl.h"
+#include "dns.h"
 #include "dns_requestacl_python.h"
 #include "dns_requestcontext_python.h"
 
 using namespace std;
 using namespace isc::util::python;
 using namespace isc::acl;
-using namespace isc::acl::python;
 using namespace isc::acl::dns;
 using namespace isc::acl::dns::python;
 
@@ -60,7 +59,8 @@ s_RequestACL::s_RequestACL() {}
 namespace {
 int
 RequestACL_init(PyObject*, PyObject*, PyObject*) {
-    PyErr_SetString(po_ACLError, "RequestACL cannot be directly constructed");
+    PyErr_SetString(getACLException("Error"),
+                    "RequestACL cannot be directly constructed");
     return (-1);
 }
 
@@ -84,7 +84,7 @@ RequestACL_execute(PyObject* po_self, PyObject* args) {
         }
     } catch (const exception& ex) {
         const string ex_what = "Failed to execute ACL: " + string(ex.what());
-        PyErr_SetString(po_ACLError, ex_what.c_str());
+        PyErr_SetString(getACLException("Error"), ex_what.c_str());
     } catch (...) {
         PyErr_SetString(PyExc_RuntimeError,
                         "Unexpected exception in executing ACL");

+ 2 - 3
src/lib/python/isc/acl/dns_requestcontext_python.cc

@@ -42,7 +42,7 @@
 #include <acl/dns.h>
 #include <acl/ip_check.h>
 
-#include "acl.h"
+#include "dns.h"
 #include "dns_requestcontext_python.h"
 
 using namespace std;
@@ -51,7 +51,6 @@ using boost::lexical_cast;
 using namespace isc;
 using namespace isc::util::python;
 using namespace isc::acl::dns;
-using namespace isc::acl::python;
 using namespace isc::acl::dns::python;
 
 namespace isc {
@@ -177,7 +176,7 @@ RequestContext_init(PyObject* po_self, PyObject* args, PyObject*) {
     } catch (const exception& ex) {
         const string ex_what = "Failed to construct RequestContext object: " +
             string(ex.what());
-        PyErr_SetString(po_ACLError, ex_what.c_str());
+        PyErr_SetString(getACLException("Error"), ex_what.c_str());
         return (-1);
     } catch (...) {
         PyErr_SetString(PyExc_RuntimeError,