2424 */
2525
2626#include "py_subinterp_thread.h"
27+ #include "py_nif.h"
2728#include <string.h>
2829#include <unistd.h>
2930#include <fcntl.h>
@@ -429,6 +430,15 @@ static void *worker_thread_main(void *arg) {
429430 PyObject * result = NULL ;
430431 PyObject * globals = ns ? ns -> globals : PyDict_New ();
431432 PyObject * locals = ns ? ns -> locals : PyDict_New ();
433+ bool owns_globals = (ns == NULL );
434+ bool owns_locals = (ns == NULL );
435+
436+ /* Check allocation if we own the dicts */
437+ if ((owns_globals && globals == NULL ) || (owns_locals && locals == NULL )) {
438+ if (owns_globals ) Py_XDECREF (globals );
439+ if (owns_locals ) Py_XDECREF (locals );
440+ break ;
441+ }
432442
433443 switch (header .req_type ) {
434444 case REQ_CALL :
@@ -447,6 +457,8 @@ static void *worker_thread_main(void *arg) {
447457 } else if (enif_get_atom (tmp_env , elements [0 ], mod_str , 256 , ERL_NIF_LATIN1 )) {
448458 /* Already filled */
449459 } else {
460+ if (owns_globals ) Py_DECREF (globals );
461+ if (owns_locals ) Py_DECREF (locals );
450462 break ;
451463 }
452464
@@ -458,6 +470,8 @@ static void *worker_thread_main(void *arg) {
458470 } else if (enif_get_atom (tmp_env , elements [1 ], func_str , 256 , ERL_NIF_LATIN1 )) {
459471 /* Already filled */
460472 } else {
473+ if (owns_globals ) Py_DECREF (globals );
474+ if (owns_locals ) Py_DECREF (locals );
461475 break ;
462476 }
463477
@@ -481,6 +495,8 @@ static void *worker_thread_main(void *arg) {
481495
482496 if (module == NULL ) {
483497 PyErr_Clear ();
498+ if (owns_globals ) Py_DECREF (globals );
499+ if (owns_locals ) Py_DECREF (locals );
484500 break ;
485501 }
486502
@@ -490,6 +506,8 @@ static void *worker_thread_main(void *arg) {
490506
491507 if (func == NULL ) {
492508 PyErr_Clear ();
509+ if (owns_globals ) Py_DECREF (globals );
510+ if (owns_locals ) Py_DECREF (locals );
493511 break ;
494512 }
495513
@@ -592,59 +610,13 @@ static void *worker_thread_main(void *arg) {
592610 break ;
593611 }
594612
595- /* Serialize result */
613+ /* Clean up owned dicts after switch completes */
614+ if (owns_globals ) Py_DECREF (globals );
615+ if (owns_locals ) Py_DECREF (locals );
616+
617+ /* Serialize result using py_to_term for full type support */
596618 if (success && result != NULL ) {
597- /* For now, just return ok atom */
598- /* TODO: Proper py_to_term conversion and ETF serialization */
599- ERL_NIF_TERM result_term ;
600- if (result == Py_None ) {
601- result_term = enif_make_atom (tmp_env , "none" );
602- } else if (PyLong_Check (result )) {
603- long val = PyLong_AsLong (result );
604- result_term = enif_make_long (tmp_env , val );
605- } else if (PyFloat_Check (result )) {
606- double val = PyFloat_AsDouble (result );
607- result_term = enif_make_double (tmp_env , val );
608- } else if (PyUnicode_Check (result )) {
609- Py_ssize_t size ;
610- const char * str = PyUnicode_AsUTF8AndSize (result , & size );
611- if (str ) {
612- ErlNifBinary bin ;
613- if (enif_alloc_binary (size , & bin )) {
614- memcpy (bin .data , str , size );
615- result_term = enif_make_binary (tmp_env , & bin );
616- } else {
617- result_term = enif_make_atom (tmp_env , "conversion_error" );
618- }
619- } else {
620- result_term = enif_make_atom (tmp_env , "conversion_error" );
621- }
622- } else if (PyBool_Check (result )) {
623- result_term = result == Py_True ?
624- enif_make_atom (tmp_env , "true" ) :
625- enif_make_atom (tmp_env , "false" );
626- } else {
627- /* Fallback: convert to string representation */
628- PyObject * str = PyObject_Str (result );
629- if (str ) {
630- Py_ssize_t size ;
631- const char * s = PyUnicode_AsUTF8AndSize (str , & size );
632- if (s ) {
633- ErlNifBinary bin ;
634- if (enif_alloc_binary (size , & bin )) {
635- memcpy (bin .data , s , size );
636- result_term = enif_make_binary (tmp_env , & bin );
637- } else {
638- result_term = enif_make_atom (tmp_env , "conversion_error" );
639- }
640- } else {
641- result_term = enif_make_atom (tmp_env , "conversion_error" );
642- }
643- Py_DECREF (str );
644- } else {
645- result_term = enif_make_atom (tmp_env , "pyobject" );
646- }
647- }
619+ ERL_NIF_TERM result_term = py_to_term (tmp_env , result );
648620 Py_XDECREF (result );
649621
650622 /* Wrap in {ok, Result} */
0 commit comments