machinekit / machinekit-cnc

CNC stack split out into a separate package
Other
60 stars 36 forks source link

TypeError: get_interpreter() returned NULL #82

Open fishpepper opened 5 years ago

fishpepper commented 5 years ago

Hi!

I am trying to build my own machinekit under a plain stretch based debian image.

I am struggling issues with getting the following error:

  File "/home/machinekit/src/machinekit/bin/axis", line 3215, in <module>
    o = MyOpengl(widgets.preview_frame, width=400, height=300, double=1, depth=1)
  File "/home/machinekit/src/machinekit/bin/axis", line 373, in __init__
    Opengl.__init__(self, *args, **kw)
  File "/home/machinekit/src/machinekit/lib/python/rs274/OpenGLTk.py", line 164, in __init__
    apply(RawOpengl.__init__, (self, master, cnf), kw)
  File "/home/machinekit/src/machinekit/lib/python/rs274/OpenGLTk.py", line 112, in __init__
    Togl.__init__(self, master, cnf, **kw)
  File "/home/machinekit/src/machinekit/lib/python/rs274/OpenGLTk.py", line 37, in __init__
    _togl.install(master.tk)
TypeError: get_interpreter() returned NULL
Exception AttributeError: "MyOpengl instance has no attribute '_dlists'" in <bound method MyOpengl.__del__ of <__main__.MyOpengl instance at 0xb4b11f08>> ignored
Shutting down and cleaning up Machinekit...

I traced it back to the file src/emc/usr_intf/axis/extensions/_toglmodule.c. This diff adds some more debug info (might be good to have it in the master branch as well):

index 6c872b5fe..2a591566b 100644
--- a/src/emc/usr_intf/axis/extensions/_toglmodule.c
+++ b/src/emc/usr_intf/axis/extensions/_toglmodule.c
@@ -22,8 +22,12 @@ static Tcl_Interp *get_interpreter(PyObject *tkapp) {
     PyObject *interpaddrobj = PyObject_CallMethod(tkapp, "interpaddr", NULL);
     if(interpaddrobj == NULL) { return NULL; }
     interpaddr = PyInt_AsLong(interpaddrobj);
+    if (PyErr_Occurred()){ 
+        PyErr_PrintEx(0);
+       return NULL;
+    }
     Py_DECREF(interpaddrobj);
-    if(interpaddr == -1) { return NULL; }
+    if((interpaddr == -1) && PyErr_Occurred()) { return NULL; }
     return (Tcl_Interp*)interpaddr;
 }

The change with the checking of == -1 is necessary as the PyInt_AsLong documentation says just checking for -1 is not correct. Anyway, that is not my issue.... Running this modified code gives me this error reason: OverflowError: Python int too large to convert to C long

Really strange... I have no idea of the internals of PyInt_AsLong but as I was curious and I tried to replace it by: interpaddr = PyInt_AsUnsignedLongLongMask(interpaddrobj); With this fix axis starts up just fine and it looks like all is working as expected. I am sure this is not the correct way of doing it. Maybe a python guru can point me in the right direction?

Simon

fishpepper commented 5 years ago

I think this might be related to that issue: https://bugs.python.org/issue18909

(my stretch image runs python 2.7.13-2)

fishpepper commented 5 years ago

It seems like the tkapp interpaddr was changed to return a Long. I am not sure why this only happens for me :-\

However this patch fixes it for me:

diff --git a/src/emc/usr_intf/axis/extensions/_toglmodule.c b/src/emc/usr_intf/axis/extensions/_toglmodule.c
index 6c872b5fe..b51b2b137 100644
--- a/src/emc/usr_intf/axis/extensions/_toglmodule.c
+++ b/src/emc/usr_intf/axis/extensions/_toglmodule.c
@@ -18,12 +18,15 @@
 static int first_time = 1;

 static Tcl_Interp *get_interpreter(PyObject *tkapp) {
-    long interpaddr;
+    void* interpaddr;
     PyObject *interpaddrobj = PyObject_CallMethod(tkapp, "interpaddr", NULL);
     if(interpaddrobj == NULL) { return NULL; }
-    interpaddr = PyInt_AsLong(interpaddrobj);
+    interpaddr = PyLong_AsVoidPtr(interpaddrobj); 
     Py_DECREF(interpaddrobj);
-    if(interpaddr == -1) { return NULL; }
+    if(PyErr_Occurred()) {
+        PyErr_PrintEx(0);
+        return NULL;
+    }
     return (Tcl_Interp*)interpaddr;
 }
ArcEye commented 5 years ago

According to your post, you are trying to build on stretch running a defunct xenomai2 kernel. What architecture has not AFAIR been divulged.

If this only happens then, I would be loathe to change the codebase for such a corner case.

ArcEye commented 5 years ago

I have just cloned and built machinekit from scratch on Buster/sid (amd64) and run the Axis sim_mm on the title code without incident. My python version is 2.7.16+ so I don't think something has radically changed in python certainly not at your version ( unless they messed it up and reverted in later versions ).

fishpepper commented 5 years ago

I am building machinekit on a beagleboneblack using the armhf stretch image.

And you are right, I am wondering why this happens only for me.. Maybe the xenomai kernel is somehow changing the way my system allocates the memory.

Anyway, it seems that the python tkinter stuff was changed a very long time ago to return a Long based on a void pointer: https://github.com/python/cpython/commit/930c3c9e43dee8ad65f33d167b0c511cd22f6334

Casting it back by using PyLong_AsVoidPtr() seems to be plausible to me. Going the way from int to long and then casting the long back to the Tcl_Interp pointer seems over complicated.

However I still do not get why this does not throw an out of range error and the asLong function does... Both should be 32bits?!