Re: PyGILState_Release called twice in embedded application

2023-03-23 Thread Arnaud Loonstra

On 23-03-2023 13:33, Barry Scott wrote:




On 23 Mar 2023, at 08:46, Arnaud Loonstra  wrote:

Hi all,

I'm running in a crash due to a ResourceWarning (some socket is not closed in a 
used module) after calling PyGILState_Release.

I'm running Python in a native thread (so a thread created by C not Python). 
I'm acquiring the GIL through PyGILState_Ensure before doing any CPYthon calls 
and releasing when finished using PyGILState_Release.

This has worked fine. But now I'm using a python module (openai) which doesn't 
close its socket correctly which results in a ResourceWarning which triggers an 
assert.

In the backtrace  (below) I can see PyGILState_Release is called again. (7) 
while I've already called it (126).

I can make the crash go away by adding

import warnings
warnings.simplefilter("ignore", ResourceWarning)

to my python code. But I'd rather prevent this from happening in the first 
place.

Any suggestion very welcomed cause I'm puzzled.


What 3rd party C extension are you running with?
I'd be surprised if the cpython code was the issue.

Barry


I'm not using any 3rd party extension myself. But the issue is caused by 
the openai module using the requests module which is not closing sockets:


https://github.com/openai/openai-python/issues/140

I'm not aware what C extensions they might use.

Btw, I've tested this with python 3.8 and 3.11.2.

Rg,

Arnaud
--
https://mail.python.org/mailman/listinfo/python-list


PyGILState_Release called twice in embedded application

2023-03-23 Thread Arnaud Loonstra

Hi all,

I'm running in a crash due to a ResourceWarning (some socket is not 
closed in a used module) after calling PyGILState_Release.


I'm running Python in a native thread (so a thread created by C not 
Python). I'm acquiring the GIL through PyGILState_Ensure before doing 
any CPYthon calls and releasing when finished using PyGILState_Release.


This has worked fine. But now I'm using a python module (openai) which 
doesn't close its socket correctly which results in a ResourceWarning 
which triggers an assert.


In the backtrace  (below) I can see PyGILState_Release is called again. 
(7) while I've already called it (126).


I can make the crash go away by adding

import warnings
warnings.simplefilter("ignore", ResourceWarning)

to my python code. But I'd rather prevent this from happening in the 
first place.


Any suggestion very welcomed cause I'm puzzled.

Rg,

Arnaud

1   __pthread_kill_implementation  pthread_kill.c   44 
0x76fcaccc
2   __pthread_kill_internalpthread_kill.c   78 
0x76fcad2f
3   __GI_raise raise.c  26 
0x76f7bef2
4   __GI_abort abort.c  79 
0x76f66472
5   __assert_fail_base assert.c 92 
0x76f66395
6   __GI___assert_fail assert.c 101 
0x76f74df2
7   PyGILState_Release pystate.c1742 
0x77abcf9f
8   tracemalloc_raw_alloc  _tracemalloc.c   779 
0x77afa803
9   tracemalloc_raw_malloc _tracemalloc.c   789 
0x77afa844
10  PyMem_RawMallocobmalloc.c   586 
0x779dab8d
11  decode_current_locale  fileutils.c  472 
0x77ada4ab
12  _Py_DecodeLocaleEx fileutils.c  598 
0x77adafce
13  unicode_decode_locale  unicodeobject.c  3970 
0x77a13b65
14  PyUnicode_DecodeLocale unicodeobject.c  4012 
0x77a18c79
15  PyErr_SetFromErrnoWithFilenameObjects  errors.c 772 
0x77a94178
16  PyErr_SetFromErrnoWithFilenameObject   errors.c 750 
0x77a942ce
17  posix_path_object_errorposixmodule.c1709 
0x77ae4201
18  path_object_error  posixmodule.c1719 
0x77ae420f
19  path_error posixmodule.c1737 
0x77ae4221
20  posix_do_stat  posixmodule.c2565 
0x77af42f7
21  os_stat_impl   posixmodule.c2897 
0x77af4491
22  os_statposixmodule.c.h  71 
0x77af45e5
23  cfunction_vectorcall_FASTCALL_KEYWORDS methodobject.c   443 
0x779d2ece
24  _PyObject_VectorcallTstate pycore_call.h92 
0x7798b579
25  PyObject_Vectorcallcall.c   299 
0x7798b65e
26  _PyEval_EvalFrameDefault   ceval.c  4772 
0x77a75453
27  _PyEval_EvalFrame  pycore_ceval.h   73 
0x77a79887
28  _PyEval_Vector ceval.c  6435 
0x77a799b1
29  _PyFunction_Vectorcall call.c   393 
0x7798b215
30  _PyObject_VectorcallTstate pycore_call.h92 
0x7798b579
31  PyObject_CallOneArgcall.c   376 
0x7798b6cd
32  call_show_warning  _warnings.c  609 
0x77a31d24
33  warn_explicit  _warnings.c  746 
0x77a3223b
34  do_warn_warnings.c  947 
0x77a3236f
35  warn_unicode   _warnings.c  1106 
0x77a32414
36  _PyErr_WarnFormatV _warnings.c  1126 
0x77a32481
37  PyErr_ResourceWarning  _warnings.c  1177 
0x77a32d38
38  sock_finalize  socketmodule.c   5073 
0x76840cf3
39  PyObject_CallFinalizer object.c 208 
0x779d6449
40  PyObject_CallFinalizerFromDealloc  object.c 226 
0x779d75ac
41  subtype_dealloctypeobject.c 1382 
0x779ecf81
42  _Py_Deallocobject.c 2390 
0x779d6c38
43  Py_DECREF  object.h 527 
0x779c116e
44  Py_XDECREF object.h 602 
0x779c118d
45  free_keys_object   dictobject.c 664 
0x779c120a
46  dictkeys_decrefdictobject.c 324 
0x779c130f
47  dict_dealloc   dictobject.c 2378 
0x779c2eeb
48  _Py_Deallocobject.c 2390 
0x779d6c38
49  Py_DECREF  object.h 5

Re: Embedding Python crash on PyTuple_New

2021-11-24 Thread Arnaud Loonstra


On 24-11-2021 01:46, MRAB wrote:

On 2021-11-23 20:25, Arnaud Loonstra wrote:

On 23-11-2021 18:31, MRAB wrote:

On 2021-11-23 16:04, Arnaud Loonstra wrote:

On 23-11-2021 16:37, MRAB wrote:

On 2021-11-23 15:17, MRAB wrote:

On 2021-11-23 14:44, Arnaud Loonstra wrote:

On 23-11-2021 15:34, MRAB wrote:

On 2021-11-23 12:07, Arnaud Loonstra wrote:

Hi,

I've got Python embedded successfully in a program up until now 
as I'm
now running into weird GC related segfaults. I'm currently 
trying to

debug this but my understanding of CPython limits me here.

I'm creating a Tuple in C but it crashes on creating it after a 
while.

It doesn't make sense which makes me wonder something else must be
happening? Could be it just crashes here because the GC is 
cleaning up
stuff completely unrelated to the allocation of the new tuple? 
How can I

troubleshoot this?

I've got CPython compiled with  --with-valgrind --without-pymalloc
--with-pydebug

In C I'm creating a tuple with the following method:

static PyObject *
s_py_zosc_tuple(pythonactor_t *self, zosc_t *oscmsg)
{
  assert(self);
  assert(oscmsg);
  char *format = zosc_format(oscmsg);

  PyObject *rettuple = PyTuple_New((Py_ssize_t) 
strlen(format) );


It segfaults here (frame 16) after 320 times (consistently)


1   __GI_raise raise.c  49   0x772c4e71
2   __GI_abort abort.c  79   0x772ae536
3   fatal_error    pylifecycle.c    2183 0x77d84b4f
4   Py_FatalError  pylifecycle.c    2193 0x77d878b2
5   _PyObject_AssertFailed object.c 2200 0x77c93cf2
6   visit_decref   gcmodule.c   378  0x77dadfd5
7   tupletraverse  tupleobject.c    623  0x77ca3e81
8   subtract_refs  gcmodule.c   406  0x77dad340
9   collect    gcmodule.c   1054 0x77dae838
10  collect_with_callback  gcmodule.c   1240 0x77daf17b
11  collect_generations    gcmodule.c   1262 0x77daf3f6
12  _PyObject_GC_Alloc gcmodule.c   1977 0x77daf4f2
13  _PyObject_GC_Malloc    gcmodule.c   1987 0x77dafebc
14  _PyObject_GC_NewVar    gcmodule.c   2016 0x77daffa5
15  PyTuple_New    tupleobject.c    118  0x77ca4da7
16  s_py_zosc_tuple    pythonactor.c    366  0x5568cc82
17  pythonactor_socket pythonactor.c    664  0x5568dac7
18  pythonactor_handle_msg pythonactor.c    862  0x5568e472
19  pythonactor_handler    pythonactor.c    828  0x5568e2e2
20  sphactor_actor_run sphactor_actor.c 855  0x558cb268
... 

Any pointer really appreciated.


[snip]



Basically, yes, but I won't be surprised if it was due to too few 
INCREFs or too many DECREFs somewhere.


https://github.com/hku-ect/gazebosc/blob/505b30c46bf3f78d188c3f575c80e294d3db7e5d/Actors/pythonactor.c#L286 



Incidentally, in s_py_zosc_tuple, you're not doing "assert(rc == 0);" 
after "after zosc_pop_float" or "zosc_pop_double".


Thanks for those pointers! I think your intuition is right. I might have
found the bugger. In s_py_zosc I call Py_DECREF on pAddress and pData.
However they are acquired by PyTuple_GetItem which returns a borrowed
reference. I think pAddress and pData are then also 'decrefed' when the
pReturn tuple which contains pAddress and pData is 'decrefed'?


Yes, members of a container are DECREFed when the container is destroyed.

It's bad practice for a function to DECREF its arguments unless the 
function's sole purpose is cleanup because the function won't know where 
the arguments came from.




I'm finding it out now. What strikes me was how hard it was to debug 
this. I think it was caused because I INCREFed the return object. I 
guess I did that to workaround the wrong DECREF data in the return 
object. However that caused a hell to debug. I'm really curious what the 
best practices are for debugging embedded CPython.


Thanks big time for your feedback!
--
https://mail.python.org/mailman/listinfo/python-list


Re: Embedding Python crash on PyTuple_New

2021-11-23 Thread Arnaud Loonstra

On 23-11-2021 18:31, MRAB wrote:

On 2021-11-23 16:04, Arnaud Loonstra wrote:

On 23-11-2021 16:37, MRAB wrote:

On 2021-11-23 15:17, MRAB wrote:

On 2021-11-23 14:44, Arnaud Loonstra wrote:

On 23-11-2021 15:34, MRAB wrote:

On 2021-11-23 12:07, Arnaud Loonstra wrote:

Hi,

I've got Python embedded successfully in a program up until now 
as I'm

now running into weird GC related segfaults. I'm currently trying to
debug this but my understanding of CPython limits me here.

I'm creating a Tuple in C but it crashes on creating it after a 
while.

It doesn't make sense which makes me wonder something else must be
happening? Could be it just crashes here because the GC is 
cleaning up
stuff completely unrelated to the allocation of the new tuple? 
How can I

troubleshoot this?

I've got CPython compiled with  --with-valgrind --without-pymalloc
--with-pydebug

In C I'm creating a tuple with the following method:

static PyObject *
s_py_zosc_tuple(pythonactor_t *self, zosc_t *oscmsg)
{
  assert(self);
  assert(oscmsg);
  char *format = zosc_format(oscmsg);

  PyObject *rettuple = PyTuple_New((Py_ssize_t) 
strlen(format) );


It segfaults here (frame 16) after 320 times (consistently)


1   __GI_raise raise.c  49   0x772c4e71
2   __GI_abort abort.c  79   0x772ae536
3   fatal_error    pylifecycle.c    2183 0x77d84b4f
4   Py_FatalError  pylifecycle.c    2193 0x77d878b2
5   _PyObject_AssertFailed object.c 2200 0x77c93cf2
6   visit_decref   gcmodule.c   378  0x77dadfd5
7   tupletraverse  tupleobject.c    623  0x77ca3e81
8   subtract_refs  gcmodule.c   406  0x77dad340
9   collect    gcmodule.c   1054 0x77dae838
10  collect_with_callback  gcmodule.c   1240 0x77daf17b
11  collect_generations    gcmodule.c   1262 0x77daf3f6
12  _PyObject_GC_Alloc gcmodule.c   1977 0x77daf4f2
13  _PyObject_GC_Malloc    gcmodule.c   1987 0x77dafebc
14  _PyObject_GC_NewVar    gcmodule.c   2016 0x77daffa5
15  PyTuple_New    tupleobject.c    118  0x77ca4da7
16  s_py_zosc_tuple    pythonactor.c    366  0x5568cc82
17  pythonactor_socket pythonactor.c    664  0x5568dac7
18  pythonactor_handle_msg pythonactor.c    862  0x5568e472
19  pythonactor_handler    pythonactor.c    828  0x5568e2e2
20  sphactor_actor_run sphactor_actor.c 855  0x558cb268
... 

Any pointer really appreciated.

You're creating a tuple that'll have the same number of members as 
the length of a string? That looks strange to me.


How are you setting the tuple's members?


It's from a serialisation format called OSC. The string describes the
type of bytes, every character is a type.

I'm creating the tuple as follows:

PyObject *rettuple = PyTuple_New((Py_ssize_t) strlen(format) );

Then I iterate the OSC message using the format string, (just showing
handling an int (i))

  char type = '0';
  Py_ssize_t pos = 0;
  const void *data =  zosc_first(oscmsg, &type);
  while(data)
  {
  switch (type)
  {
  case('i'):
  {
  int32_t val = 9;
  int rc = zosc_pop_int32(oscmsg, &val);
  assert(rc == 0);
  PyObject *o = PyLong_FromLong((long)val);
  assert( o );
  rc = PyTuple_SetItem(rettuple, pos, o);
  assert(rc == 0);
  break;
  }

Full code is here:

https://github.com/hku-ect/gazebosc/blob/822452dfa27201db274d37ce09e835d98fe500b2/Actors/pythonactor.c#L360 




Looking at that code, you have:

  PyObject *o = Py_BuildValue("s#", str, 1);

what I'd check is the type of the 1 that you're passing. Wouldn't the
compiler assume that it's an int?

The format string tells the function to expect a Py_ssize_t, but how
would the compiler know that?

Looking at https://www.mankier.com/3/zosc, it says for 'T' and 'F' 
"(no value required)", but you're doing:


 int rc = zosc_pop_bool(oscmsg, &bl);

If no value is required, is there a bool there to be popped?


The value is only required to set a user provided boolean to the value
in the message. There's no boolean value encoded in the message, only
the T and F in the format string.

With regards to the Py_BuildValue("s#", str, 1);, that's a valid point.
I'll fix that. However in the segfaults I'm testing that code is not
touched.


You can use "C" as a format string for Py_BuildValue to convert a C int 
representing a character to a Python string.



I'm now testing different parts of the code to see if it runs stable.
I've found it runs stable if I do not process the returned tuple.

PyObject *pReturn = PyObject_CallMethod(self-&

Re: Embedding Python crash on PyTuple_New

2021-11-23 Thread Arnaud Loonstra

On 23-11-2021 16:37, MRAB wrote:

On 2021-11-23 15:17, MRAB wrote:

On 2021-11-23 14:44, Arnaud Loonstra wrote:

On 23-11-2021 15:34, MRAB wrote:

On 2021-11-23 12:07, Arnaud Loonstra wrote:

Hi,

I've got Python embedded successfully in a program up until now as I'm
now running into weird GC related segfaults. I'm currently trying to
debug this but my understanding of CPython limits me here.

I'm creating a Tuple in C but it crashes on creating it after a while.
It doesn't make sense which makes me wonder something else must be
happening? Could be it just crashes here because the GC is cleaning up
stuff completely unrelated to the allocation of the new tuple? How 
can I

troubleshoot this?

I've got CPython compiled with  --with-valgrind --without-pymalloc
--with-pydebug

In C I'm creating a tuple with the following method:

static PyObject *
s_py_zosc_tuple(pythonactor_t *self, zosc_t *oscmsg)
{
  assert(self);
  assert(oscmsg);
  char *format = zosc_format(oscmsg);

  PyObject *rettuple = PyTuple_New((Py_ssize_t) strlen(format) );

It segfaults here (frame 16) after 320 times (consistently)


1   __GI_raise raise.c  49   0x772c4e71
2   __GI_abort abort.c  79   0x772ae536
3   fatal_error    pylifecycle.c    2183 0x77d84b4f
4   Py_FatalError  pylifecycle.c    2193 0x77d878b2
5   _PyObject_AssertFailed object.c 2200 0x77c93cf2
6   visit_decref   gcmodule.c   378  0x77dadfd5
7   tupletraverse  tupleobject.c    623  0x77ca3e81
8   subtract_refs  gcmodule.c   406  0x77dad340
9   collect    gcmodule.c   1054 0x77dae838
10  collect_with_callback  gcmodule.c   1240 0x77daf17b
11  collect_generations    gcmodule.c   1262 0x77daf3f6
12  _PyObject_GC_Alloc gcmodule.c   1977 0x77daf4f2
13  _PyObject_GC_Malloc    gcmodule.c   1987 0x77dafebc
14  _PyObject_GC_NewVar    gcmodule.c   2016 0x77daffa5
15  PyTuple_New    tupleobject.c    118  0x77ca4da7
16  s_py_zosc_tuple    pythonactor.c    366  0x5568cc82
17  pythonactor_socket pythonactor.c    664  0x5568dac7
18  pythonactor_handle_msg pythonactor.c    862  0x5568e472
19  pythonactor_handler    pythonactor.c    828  0x5568e2e2
20  sphactor_actor_run sphactor_actor.c 855  0x558cb268
... 

Any pointer really appreciated.

You're creating a tuple that'll have the same number of members as 
the length of a string? That looks strange to me.


How are you setting the tuple's members?


It's from a serialisation format called OSC. The string describes the
type of bytes, every character is a type.

I'm creating the tuple as follows:

PyObject *rettuple = PyTuple_New((Py_ssize_t) strlen(format) );

Then I iterate the OSC message using the format string, (just showing
handling an int (i))

  char type = '0';
  Py_ssize_t pos = 0;
  const void *data =  zosc_first(oscmsg, &type);
  while(data)
  {
  switch (type)
  {
  case('i'):
  {
  int32_t val = 9;
  int rc = zosc_pop_int32(oscmsg, &val);
  assert(rc == 0);
  PyObject *o = PyLong_FromLong((long)val);
  assert( o );
  rc = PyTuple_SetItem(rettuple, pos, o);
  assert(rc == 0);
  break;
  }

Full code is here:

https://github.com/hku-ect/gazebosc/blob/822452dfa27201db274d37ce09e835d98fe500b2/Actors/pythonactor.c#L360 




Looking at that code, you have:

  PyObject *o = Py_BuildValue("s#", str, 1);

what I'd check is the type of the 1 that you're passing. Wouldn't the
compiler assume that it's an int?

The format string tells the function to expect a Py_ssize_t, but how
would the compiler know that?

Looking at https://www.mankier.com/3/zosc, it says for 'T' and 'F' "(no 
value required)", but you're doing:


     int rc = zosc_pop_bool(oscmsg, &bl);

If no value is required, is there a bool there to be popped?


The value is only required to set a user provided boolean to the value 
in the message. There's no boolean value encoded in the message, only 
the T and F in the format string.


With regards to the Py_BuildValue("s#", str, 1);, that's a valid point. 
I'll fix that. However in the segfaults I'm testing that code is not 
touched.


I'm now testing different parts of the code to see if it runs stable. 
I've found it runs stable if I do not process the returned tuple.


PyObject *pReturn = PyObject_CallMethod(self->pyinstance,
"handleSocket", "sOsss",
oscaddress,
py_osctuple,
ev->type, ev->name, strdup(ev->u

Re: Embedding Python crash on PyTuple_New

2021-11-23 Thread Arnaud Loonstra

On 23-11-2021 15:34, MRAB wrote:

On 2021-11-23 12:07, Arnaud Loonstra wrote:

Hi,

I've got Python embedded successfully in a program up until now as I'm
now running into weird GC related segfaults. I'm currently trying to
debug this but my understanding of CPython limits me here.

I'm creating a Tuple in C but it crashes on creating it after a while.
It doesn't make sense which makes me wonder something else must be
happening? Could be it just crashes here because the GC is cleaning up
stuff completely unrelated to the allocation of the new tuple? How can I
troubleshoot this?

I've got CPython compiled with  --with-valgrind --without-pymalloc
--with-pydebug

In C I'm creating a tuple with the following method:

static PyObject *
s_py_zosc_tuple(pythonactor_t *self, zosc_t *oscmsg)
{
  assert(self);
  assert(oscmsg);
  char *format = zosc_format(oscmsg);

  PyObject *rettuple = PyTuple_New((Py_ssize_t) strlen(format) );

It segfaults here (frame 16) after 320 times (consistently)


1   __GI_raise raise.c  49   0x772c4e71
2   __GI_abort abort.c  79   0x772ae536
3   fatal_error    pylifecycle.c    2183 0x77d84b4f
4   Py_FatalError  pylifecycle.c    2193 0x77d878b2
5   _PyObject_AssertFailed object.c 2200 0x77c93cf2
6   visit_decref   gcmodule.c   378  0x77dadfd5
7   tupletraverse  tupleobject.c    623  0x77ca3e81
8   subtract_refs  gcmodule.c   406  0x77dad340
9   collect    gcmodule.c   1054 0x77dae838
10  collect_with_callback  gcmodule.c   1240 0x77daf17b
11  collect_generations    gcmodule.c   1262 0x77daf3f6
12  _PyObject_GC_Alloc gcmodule.c   1977 0x77daf4f2
13  _PyObject_GC_Malloc    gcmodule.c   1987 0x77dafebc
14  _PyObject_GC_NewVar    gcmodule.c   2016 0x77daffa5
15  PyTuple_New    tupleobject.c    118  0x77ca4da7
16  s_py_zosc_tuple    pythonactor.c    366  0x5568cc82
17  pythonactor_socket pythonactor.c    664  0x5568dac7
18  pythonactor_handle_msg pythonactor.c    862  0x5568e472
19  pythonactor_handler    pythonactor.c    828  0x5568e2e2
20  sphactor_actor_run sphactor_actor.c 855  0x558cb268
... 

Any pointer really appreciated.

You're creating a tuple that'll have the same number of members as the 
length of a string? That looks strange to me.


How are you setting the tuple's members?


It's from a serialisation format called OSC. The string describes the 
type of bytes, every character is a type.


I'm creating the tuple as follows:

PyObject *rettuple = PyTuple_New((Py_ssize_t) strlen(format) );

Then I iterate the OSC message using the format string, (just showing 
handling an int (i))


char type = '0';
Py_ssize_t pos = 0;
const void *data =  zosc_first(oscmsg, &type);
while(data)
{
switch (type)
{
case('i'):
{
int32_t val = 9;
int rc = zosc_pop_int32(oscmsg, &val);
assert(rc == 0);
PyObject *o = PyLong_FromLong((long)val);
assert( o );
rc = PyTuple_SetItem(rettuple, pos, o);
assert(rc == 0);
break;
}

Full code is here:

https://github.com/hku-ect/gazebosc/blob/822452dfa27201db274d37ce09e835d98fe500b2/Actors/pythonactor.c#L360

--
https://mail.python.org/mailman/listinfo/python-list


Re: Embedding Python crash on PyTuple_New

2021-11-23 Thread Arnaud Loonstra

On 23-11-2021 13:07, Arnaud Loonstra wrote:

Hi,

I've got Python embedded successfully in a program up until now as I'm 
now running into weird GC related segfaults. I'm currently trying to 
debug this but my understanding of CPython limits me here.


I'm creating a Tuple in C but it crashes on creating it after a while. 
It doesn't make sense which makes me wonder something else must be 
happening? Could be it just crashes here because the GC is cleaning up 
stuff completely unrelated to the allocation of the new tuple? How can I 
troubleshoot this?


I've got CPython compiled with  --with-valgrind --without-pymalloc 
--with-pydebug


In C I'm creating a tuple with the following method:

static PyObject *
s_py_zosc_tuple(pythonactor_t *self, zosc_t *oscmsg)
{
     assert(self);
     assert(oscmsg);
     char *format = zosc_format(oscmsg);

     PyObject *rettuple = PyTuple_New((Py_ssize_t) strlen(format) );

It segfaults here (frame 16) after 320 times (consistently)

1   __GI_raise raise.c  49   0x772c4e71
2   __GI_abort abort.c  79   0x772ae536
3   fatal_error    pylifecycle.c    2183 0x77d84b4f
4   Py_FatalError  pylifecycle.c    2193 0x77d878b2
5   _PyObject_AssertFailed object.c 2200 0x77c93cf2
6   visit_decref   gcmodule.c   378  0x77dadfd5
7   tupletraverse  tupleobject.c    623  0x77ca3e81
8   subtract_refs  gcmodule.c   406  0x77dad340
9   collect    gcmodule.c   1054 0x77dae838
10  collect_with_callback  gcmodule.c   1240 0x77daf17b
11  collect_generations    gcmodule.c   1262 0x77daf3f6
12  _PyObject_GC_Alloc gcmodule.c   1977 0x77daf4f2
13  _PyObject_GC_Malloc    gcmodule.c   1987 0x77dafebc
14  _PyObject_GC_NewVar    gcmodule.c   2016 0x77daffa5
15  PyTuple_New    tupleobject.c    118  0x77ca4da7
16  s_py_zosc_tuple    pythonactor.c    366  0x5568cc82
17  pythonactor_socket pythonactor.c    664  0x5568dac7
18  pythonactor_handle_msg pythonactor.c    862  0x5568e472
19  pythonactor_handler    pythonactor.c    828  0x5568e2e2
20  sphactor_actor_run sphactor_actor.c 855  0x558cb268
... 

Any pointer really appreciated.


I've found enabling PYTHONTRACEMALLOC=1 in the environment gives me a 
pointer to where to offending block was allocated.


I'm calling this method from C:

18def handleSocket(self, addr, data, type, name, uuid):
19if addr == "/pulse":
20self.lampval += 1
21return (addr, [0,0])

Modules/gcmodule.c:108: gc_decref: Assertion "gc_get_refs(g) > 0" 
failed: refcount is too small

Memory block allocated at (most recent call first):
  File "/home/arnaud/src/build-gazebosc-Desktop-Debug/bin/lampen.py", 
line 21


object address  : 0x7fffd81154c0
object refcount : 1
object type : 0x77f3df20
object type name: list
object repr : [117, 0]

Fatal Python error: _PyObject_AssertFailed
Python runtime state: initialized

Current thread 0x72481640 (most recent call first):
  File "/home/arnaud/src/build-gazebosc-Desktop-Debug/bin/lampen.py", 
line 21 in handleSocket


Thread 0x75d288c0 (most recent call first):


Now it clearly says the refcount is 1 so I'm puzzling what it means?

Rg,

Arnaud

--
https://mail.python.org/mailman/listinfo/python-list


Embedding Python crash on PyTuple_New

2021-11-23 Thread Arnaud Loonstra

Hi,

I've got Python embedded successfully in a program up until now as I'm 
now running into weird GC related segfaults. I'm currently trying to 
debug this but my understanding of CPython limits me here.


I'm creating a Tuple in C but it crashes on creating it after a while. 
It doesn't make sense which makes me wonder something else must be 
happening? Could be it just crashes here because the GC is cleaning up 
stuff completely unrelated to the allocation of the new tuple? How can I 
troubleshoot this?


I've got CPython compiled with  --with-valgrind --without-pymalloc 
--with-pydebug


In C I'm creating a tuple with the following method:

static PyObject *
s_py_zosc_tuple(pythonactor_t *self, zosc_t *oscmsg)
{
assert(self);
assert(oscmsg);
char *format = zosc_format(oscmsg);

PyObject *rettuple = PyTuple_New((Py_ssize_t) strlen(format) );

It segfaults here (frame 16) after 320 times (consistently) 



1   __GI_raise raise.c  49   0x772c4e71
2   __GI_abort abort.c  79   0x772ae536
3   fatal_errorpylifecycle.c2183 0x77d84b4f
4   Py_FatalError  pylifecycle.c2193 0x77d878b2
5   _PyObject_AssertFailed object.c 2200 0x77c93cf2
6   visit_decref   gcmodule.c   378  0x77dadfd5
7   tupletraverse  tupleobject.c623  0x77ca3e81
8   subtract_refs  gcmodule.c   406  0x77dad340
9   collectgcmodule.c   1054 0x77dae838
10  collect_with_callback  gcmodule.c   1240 0x77daf17b
11  collect_generationsgcmodule.c   1262 0x77daf3f6
12  _PyObject_GC_Alloc gcmodule.c   1977 0x77daf4f2
13  _PyObject_GC_Mallocgcmodule.c   1987 0x77dafebc
14  _PyObject_GC_NewVargcmodule.c   2016 0x77daffa5
15  PyTuple_Newtupleobject.c118  0x77ca4da7
16  s_py_zosc_tuplepythonactor.c366  0x5568cc82
17  pythonactor_socket pythonactor.c664  0x5568dac7
18  pythonactor_handle_msg pythonactor.c862  0x5568e472
19  pythonactor_handlerpythonactor.c828  0x5568e2e2
20  sphactor_actor_run sphactor_actor.c 855  0x558cb268
... 

Any pointer really appreciated.

Rg,

Arnaud
--
https://mail.python.org/mailman/listinfo/python-list


Re: return a ctypes object to C

2019-11-07 Thread Arnaud Loonstra

On 31-10-2019 15:39, Arnaud Loonstra wrote:

On 31-10-2019 14:44, Thomas Jollans wrote:

On 31/10/2019 14.13, Arnaud Loonstra wrote:

On 30-10-2019 09:32, Arnaud Loonstra wrote:

Hi all,

I'm trying to wrap my head around the ctypes API. I have a C
structure I wish to create in Python and then return from python to C.

So a python method is called from C and needs to return an object
which we then process in C again.

I have a binding to access and create the C methods and structures so
in Python I can call the Zmsg() constructor. I now need to return this.

My python test method is simply:

def actor_test( *args, **kwargs):
  print("test")
  msg = Zmsg()
  frame = Zframe(b"Hello", 5)
  msg.prepend(frame)
  return msg

the method is called from C as follows:

PyObject *pReturn = PyObject_CallObject(pFunc, NULL);

This correctly calls the method. However the returned object is of
course a PyObject*. The debugger says it's

""    PyObject
  [class]    ""
  [super class]    ""
  [meta type]    ""
  ob_refcnt    1    Py_ssize_t

However how I can I get it back to the original C type (zmsg_t *)

Any help really appreciated.



What I've found so far is that I can return the address of the ctypes
object.

msg = Zmsg()
frame = Zframe(b"Hello", 5)
msg.prepend(frame)
return addressof(msg._as_parameter_.contents)

In C I can then cast it back to the original type.

PyObject *pReturn = PyObject_CallObject(pFunc, NULL);
assert(pReturn);
long bla = PyLong_AsLong(pReturn);
zmsg_t* test = (zmsg_t *)bla;
assert(test);
char *hello = zmsg_popstr(test);
assert(hello);
assert(streq(hello, "Hello"));

This works, I'm not sure if this is the right way. It also creates a
complicated setup with the garbage collector.

Anybody better ideas?


You've already got a complicated setup with your ctypes objects...

If you're using the Python C API anyway, why would you use ctypes at
all? You can create custom Python types in C to wrap your C pointers.

Alternatively: if you're using ctypes anyway, why use the Python C API
at all? You can create C function pointers from Python functions with
ctypes.

If you're mixing two different ways of interfacing Python and C, the
result will ALWAYS be messy. Better to stick to one. Personally, I
prefer cffi or cython depending on the situation, as I find them clearer
and easier to use than ctypes. Using the Python C API directly is
usually the hardest to understand and the easiest to get wrong.

-- Thomas


Hi Thomas,

I have an engine running which can call handlers. These handlers return 
a zmsg_t (a message) which the engine then can process.


In this engine we have Python embedded and I want to use a Python method 
as a handler. To embed Python we need to use the Python C API. To 
construct a zmsg_t type in Python we need to call the corresponding C 
method and we use ctypes to do that.


I'm using a ctypes binding because it already exists, it's here: 
https://github.com/zeromq/czmq/blob/d6283985ba52fd8c3f8fbdc7cd5c08372ff69ca1/bindings/python/czmq/_czmq_ctypes.py#L4392 



I know I can use cffi for example but that's IMHO just a ctypes 
alternative.


Are you saying it's better to create some approach to create a zmsg_t 
using the Python C API?


Please enlighten me if this should be done differently.

Rg,

Arnaud


Ok, you're reply triggered me to do some more reading into the C-API. 
I've found I can do it all using the C-API. Especially this guide was 
very helpful for my situation:


https://docs.python.org/3/extending/newtypes_tutorial.html

Thnx,

Arnaud
--
https://mail.python.org/mailman/listinfo/python-list


Re: return a ctypes object to C

2019-10-31 Thread Arnaud Loonstra

On 31-10-2019 14:44, Thomas Jollans wrote:

On 31/10/2019 14.13, Arnaud Loonstra wrote:

On 30-10-2019 09:32, Arnaud Loonstra wrote:

Hi all,

I'm trying to wrap my head around the ctypes API. I have a C
structure I wish to create in Python and then return from python to C.

So a python method is called from C and needs to return an object
which we then process in C again.

I have a binding to access and create the C methods and structures so
in Python I can call the Zmsg() constructor. I now need to return this.

My python test method is simply:

def actor_test( *args, **kwargs):
  print("test")
  msg = Zmsg()
  frame = Zframe(b"Hello", 5)
  msg.prepend(frame)
  return msg

the method is called from C as follows:

PyObject *pReturn = PyObject_CallObject(pFunc, NULL);

This correctly calls the method. However the returned object is of
course a PyObject*. The debugger says it's

""    PyObject
  [class]    ""
  [super class]    ""
  [meta type]    ""
  ob_refcnt    1    Py_ssize_t

However how I can I get it back to the original C type (zmsg_t *)

Any help really appreciated.



What I've found so far is that I can return the address of the ctypes
object.

msg = Zmsg()
frame = Zframe(b"Hello", 5)
msg.prepend(frame)
return addressof(msg._as_parameter_.contents)

In C I can then cast it back to the original type.

PyObject *pReturn = PyObject_CallObject(pFunc, NULL);
assert(pReturn);
long bla = PyLong_AsLong(pReturn);
zmsg_t* test = (zmsg_t *)bla;
assert(test);
char *hello = zmsg_popstr(test);
assert(hello);
assert(streq(hello, "Hello"));

This works, I'm not sure if this is the right way. It also creates a
complicated setup with the garbage collector.

Anybody better ideas?


You've already got a complicated setup with your ctypes objects...

If you're using the Python C API anyway, why would you use ctypes at
all? You can create custom Python types in C to wrap your C pointers.

Alternatively: if you're using ctypes anyway, why use the Python C API
at all? You can create C function pointers from Python functions with
ctypes.

If you're mixing two different ways of interfacing Python and C, the
result will ALWAYS be messy. Better to stick to one. Personally, I
prefer cffi or cython depending on the situation, as I find them clearer
and easier to use than ctypes. Using the Python C API directly is
usually the hardest to understand and the easiest to get wrong.

-- Thomas


Hi Thomas,

I have an engine running which can call handlers. These handlers return 
a zmsg_t (a message) which the engine then can process.


In this engine we have Python embedded and I want to use a Python method 
as a handler. To embed Python we need to use the Python C API. To 
construct a zmsg_t type in Python we need to call the corresponding C 
method and we use ctypes to do that.


I'm using a ctypes binding because it already exists, it's here: 
https://github.com/zeromq/czmq/blob/d6283985ba52fd8c3f8fbdc7cd5c08372ff69ca1/bindings/python/czmq/_czmq_ctypes.py#L4392


I know I can use cffi for example but that's IMHO just a ctypes 
alternative.


Are you saying it's better to create some approach to create a zmsg_t 
using the Python C API?


Please enlighten me if this should be done differently.

Rg,

Arnaud
--
https://mail.python.org/mailman/listinfo/python-list


Re: return a ctypes object to C

2019-10-31 Thread Arnaud Loonstra

On 30-10-2019 09:32, Arnaud Loonstra wrote:

Hi all,

I'm trying to wrap my head around the ctypes API. I have a C structure I 
wish to create in Python and then return from python to C.


So a python method is called from C and needs to return an object which 
we then process in C again.


I have a binding to access and create the C methods and structures so in 
Python I can call the Zmsg() constructor. I now need to return this.


My python test method is simply:

def actor_test( *args, **kwargs):
     print("test")
     msg = Zmsg()
     frame = Zframe(b"Hello", 5)
     msg.prepend(frame)
     return msg

the method is called from C as follows:

PyObject *pReturn = PyObject_CallObject(pFunc, NULL);

This correctly calls the method. However the returned object is of 
course a PyObject*. The debugger says it's


""    PyObject
     [class]    ""
     [super class]    ""
     [meta type]    ""
     ob_refcnt    1    Py_ssize_t

However how I can I get it back to the original C type (zmsg_t *)

Any help really appreciated.



What I've found so far is that I can return the address of the ctypes 
object.


msg = Zmsg()
frame = Zframe(b"Hello", 5)
msg.prepend(frame)
return addressof(msg._as_parameter_.contents)

In C I can then cast it back to the original type.

PyObject *pReturn = PyObject_CallObject(pFunc, NULL);
assert(pReturn);
long bla = PyLong_AsLong(pReturn);
zmsg_t* test = (zmsg_t *)bla;
assert(test);
char *hello = zmsg_popstr(test);
assert(hello);
assert(streq(hello, "Hello"));

This works, I'm not sure if this is the right way. It also creates a 
complicated setup with the garbage collector.


Anybody better ideas?

Rg,

Arnaud
--
https://mail.python.org/mailman/listinfo/python-list


return a ctypes object to C

2019-10-30 Thread Arnaud Loonstra

Hi all,

I'm trying to wrap my head around the ctypes API. I have a C structure I 
wish to create in Python and then return from python to C.


So a python method is called from C and needs to return an object which 
we then process in C again.


I have a binding to access and create the C methods and structures so in 
Python I can call the Zmsg() constructor. I now need to return this.


My python test method is simply:

def actor_test( *args, **kwargs):
print("test")
msg = Zmsg()
frame = Zframe(b"Hello", 5)
msg.prepend(frame)
return msg

the method is called from C as follows:

PyObject *pReturn = PyObject_CallObject(pFunc, NULL);

This correctly calls the method. However the returned object is of 
course a PyObject*. The debugger says it's


"" PyObject
[class] ""  
[super class]   ""  
[meta type] ""
ob_refcnt   1   Py_ssize_t

However how I can I get it back to the original C type (zmsg_t *)

Any help really appreciated.

Rg,

Arnaud
--
https://mail.python.org/mailman/listinfo/python-list


Embedding Python (3.7) on OSX crash on Py_Initialize when run as bundle

2019-02-28 Thread Arnaud Loonstra

Hi,

I'm trying to wrap my head around an OSX app which has python embedded. 
This works fine if I run the build on the same machine as it is build on.


However when using Travis to build the app I can only get it to run from 
the terminal. A double click on the appdir (or using open) results in a 
crash.


trace:
0   libsystem_kernel.dylib  0x7fffb9d6cd42 __pthread_kill + 10
1   libsystem_pthread.dylib 0x7fffb9e5a457 pthread_kill + 90
2   libsystem_c.dylib   0x7fffb9cd24bb __abort + 140
3   libsystem_c.dylib   0x7fffb9cd242f abort + 144
4   com.your-company-name.www   0x000108c6674e fatal_error + 606
5   com.your-company-name.www 	0x000108c65b3a _Py_FatalInitError 
+ 26

6   com.your-company-name.www   0x000108c65bbe Py_Initialize + 126

I can't figure out what is going wrong. I can only guess that's there's 
something preventing it to access the python files?


The build log on travis is here:
https://travis-ci.org/hku-ect/NatNet2OSCbridge/jobs/499348594

It's artefact is here:
https://pong.hku.nl/~buildbot/nightly/NatNet2OSCbridge_osx_7ceb.zip

Python is build with the following flags:
./configure --prefix 
$HOME/openFrameworks/apps/devApps/$APPNAME/bin/python --disable-shared 
--with-openssl=$(brew --prefix openssl);


Anybody any pointers or advice?

Rg,

Arnaud
--
https://mail.python.org/mailman/listinfo/python-list