summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Andreoli <dave@gurumeditation.it>2018-01-02 21:52:57 +0100
committerDave Andreoli <dave@gurumeditation.it>2018-01-02 21:52:57 +0100
commita2b24d09489930beb949fb1fbc836cc5058f561f (patch)
treef0b3c9c40650057e02184ea5153c4b43ccba7a1a
parentb9ed84f4edc505737c9f9d034c24e080f5fa2242 (diff)
downloadefl-a2b24d09489930beb949fb1fbc836cc5058f561f.tar.gz
Pyolian: fix segfault on shutdown
also improve abit all_namespaces performance by using a set (hashable)
-rw-r--r--src/scripts/pyolian/eolian.py35
-rwxr-xr-xsrc/scripts/pyolian/generator.py4
-rwxr-xr-xsrc/scripts/pyolian/test_eolian.py2
3 files changed, 25 insertions, 16 deletions
diff --git a/src/scripts/pyolian/eolian.py b/src/scripts/pyolian/eolian.py
index 645b463278..1b43d5e737 100644
--- a/src/scripts/pyolian/eolian.py
+++ b/src/scripts/pyolian/eolian.py
@@ -24,6 +24,7 @@ a way that this folder will be available on PYTHON_PATH, fe:
"""
from enum import IntEnum
+import atexit
from ctypes import cast, byref, c_char_p, c_void_p, c_int
import ctypes
@@ -32,6 +33,7 @@ try:
except ImportError:
from eolian_lib import lib
+_already_halted = False
### Eolian Enums ############################################################
@@ -303,13 +305,16 @@ class Eolian_Unit(EolianBaseObject):
@property
def all_namespaces(self):
# TODO find a better way to find namespaces (maybe inside eolian?)
- nspaces = []
- for cls in self.all_classes:
- ns = Namespace(self, cls.namespace)
- if not ns in nspaces:
- nspaces.append(ns)
- nspaces.sort()
- return nspaces
+ nspaces = set()
+ for obj in self.all_classes:
+ nspaces.add(Namespace(self, obj.namespace))
+ for obj in self.typedecl_all_aliases:
+ nspaces.add(Namespace(self, obj.namespace))
+ for obj in self.typedecl_all_structs:
+ nspaces.add(Namespace(self, obj.namespace))
+ for obj in self.typedecl_all_enums:
+ nspaces.add(Namespace(self, obj.namespace))
+ return sorted(nspaces)
def namespace_get_by_name(self, name):
return Namespace(self, name)
@@ -392,10 +397,8 @@ class Eolian(Eolian_Unit):
self._obj = lib.eolian_new() # Eolian *
def __del__(self):
- # TODO I'm not sure about this, It is automatically called on gc, that
- # is fired after atexit (eolian_shutdown). Thus causing a segfault
- # if the user do not call del before exit.
- lib.eolian_free(self._obj)
+ if not _already_halted: # do not free after eolian_shutdown
+ lib.eolian_free(self._obj)
def file_parse(self, filepath):
c_unit = lib.eolian_file_parse(self._obj, _str_to_bytes(filepath))
@@ -449,6 +452,9 @@ class Namespace(object):
def __gt__(self, other):
return self.name > other.name
+ def __hash__(self):
+ return hash(self._name)
+
@property
def name(self):
return self._name
@@ -1420,10 +1426,13 @@ def _str_to_py(s):
### module init/shutdown ####################################################
+def _cleanup():
+ global _already_halted
+ lib.eolian_shutdown()
+ _already_halted = True
-import atexit
lib.eolian_init()
-atexit.register(lambda: lib.eolian_shutdown())
+atexit.register(_cleanup)
### API coverage statistics #################################################
diff --git a/src/scripts/pyolian/generator.py b/src/scripts/pyolian/generator.py
index 140b620a6d..c50eead66a 100755
--- a/src/scripts/pyolian/generator.py
+++ b/src/scripts/pyolian/generator.py
@@ -174,8 +174,8 @@ class Template(pyratemp.Template):
ctx['alias'] = eolian_db.typedecl_alias_get_by_name(alias)
if verbose and filename:
- print('generating "{}" from template "{}"'.format(
- filename, self.template_filename))
+ print("rendering: {} => {}".format(
+ self.template_filename, filename))
# render with the augmented context
output = self(**ctx)
diff --git a/src/scripts/pyolian/test_eolian.py b/src/scripts/pyolian/test_eolian.py
index c7b9769b4e..5e43f727a6 100755
--- a/src/scripts/pyolian/test_eolian.py
+++ b/src/scripts/pyolian/test_eolian.py
@@ -154,7 +154,7 @@ class TestEolianNamespace(unittest.TestCase):
for ns in state.all_namespaces:
self.assertIsInstance(ns, eolian.Namespace)
count += 1
- self.assertGreater(count, 100)
+ self.assertGreater(count, 200)
def test_namespace_equality(self):
ns1 = eolian.Namespace(state, 'Efl.Io')