# Plea for segfault assistance in PythonCall.jl

**URL:** <https://discourse.julialang.org/t/plea-for-segfault-assistance-in-pythoncall-jl/130697>\
**Category:** General Usage\
**Tags:** question\
**Created:** [July 14, 2025, 11:02am UTC](https://discourse.julialang.org/t/plea-for-segfault-assistance-in-pythoncall-jl/130697 "2025-07-14T11:02:45Z")\
**Posts on this page:** 1\
**Showing post:** 19

<div class="post-metadata">

**Author:** ![vchuravy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vchuravy/32/8_2.png) [@vchuravy](https://discourse.julialang.org/u/vchuravy)\
**Post date:** [July 14, 2025, 6:41pm UTC](https://discourse.julialang.org/t/plea-for-segfault-assistance-in-pythoncall-jl/130697/19 "2025-07-14T18:41:16Z")

</div>

So we have some more breadcrumbs to follow.

1. Let’s watch for any memory write to the object

```julia
0x00006e36383e2cc8 in gc_assert_parent_validity (parent=0x43fd6a5f76d0,
    child=0x588277d1b3c0 <jl_system_image_data+8141504>)
    at /home/vchuravy/src/julia-1.11/src/gc.c:1974
1974 if (__unlikely(!jl_is_datatype((jl_datatype_t *)child_vt) || ((jl_datatype_t *)child_vt)->smalltag)) {
(rr) watch *(uintptr_t*)0x588277d1b3c0
Hardware watchpoint 2: *(uintptr_t*)0x588277d1b3c0

```

1. Every julia object has a tag before it. If that tag is corrupted we don’t know what is stored there

```julia
(rr) p/x child_astagged
$4 = 0x588277d1b3b8
(rr) watch *(uintptr_t*)0x588277d1b3b8
Hardware watchpoint 3: *(uintptr_t*)0x588277d1b3b8

```

1. The object is currently stored in an array, so we have the “slot” address and can watch when this object got written to this array

```julia
(rr) up
#1 0x00006e36383e47b2 in gc_mark_objarray (ptls=0x5607db3e3fc0, obj_parent=0x43fd6a5f76d0, obj_begin=0x5607dbca7498, obj_end=0x5607dbca98a0, step=1,
    nptr=32370) at /home/vchuravy/src/julia-1.11/src/gc.c:2245
(rr) p slot
$5 = (jl_value_t **) 0x5607dbca7498
(rr) watch *(jl_value_t **) 0x5607dbca7498
Hardware watchpoint 4: *(jl_value_t **) 0x5607dbca7498
(rr) rc

```

Okay, let’s see if we hit any useful breakpoints.

```julia
Continuing.
Downloading 343.98 K source file /usr/src/debug/python/Python-3.13.5/Objects/typeobject.c

Thread 2 hit Hardware watchpoint 3: *(uintptr_t*)0x588277d1b3b8

Old value = 65703
New value = 167
set_version_unlocked (tp=0x588277d1b220 <jl_system_image_data+8141088>, version=238) at Objects/typeobject.c:972
972 tp->tp_versions_used++;

```

Uhm, why is Python smashing our type-tag?

```julia
(rr) bt
#0 set_version_unlocked (tp=0x588277d1b220 <jl_system_image_data+8141088>,
    version=238) at Objects/typeobject.c:972
#1 assign_version_tag (interp=interp@entry=0x506a4085a5b0 <_PyRuntime+88400>,
    type=<optimized out>) at Objects/typeobject.c:1164
#2 0x0000506a404b0ce3 in assign_version_tag (
    interp=interp@entry=0x506a4085a5b0 <_PyRuntime+88400>,
    type=<optimized out>) at Objects/typeobject.c:1154
#3 0x0000506a404b0ce3 in assign_version_tag (
    interp=interp@entry=0x506a4085a5b0 <_PyRuntime+88400>,
    type=type@entry=0x5607dba92b90) at Objects/typeobject.c:1154
#4 0x0000506a4056395a in _PyType_LookupRef (type=0x5607dba92b90,
    name=0x506a4084e510 <_PyRuntime+39088>) at Objects/typeobject.c:5293
#5 _Py_slot_tp_getattr_hook (self=0x548276983940, name=0x321c2d527a20)
    at Objects/typeobject.c:9629
#6 0x0000506a404bc3c2 in PyObject_GetAttr (v=0x548276983940,
    name=0x321c2d527a20) at Objects/object.c:1261
#7 0x0000506a404f377f in _PyObject_GetMethod (obj=0x548276983940,
    name=0x321c2d527a20, method=0x7ffd67ad4fb8) at Objects/object.c:1552
#8 0x0000506a404d3218 in _PyEval_EvalFrameDefault (tstate=<optimized out>,
    frame=<optimized out>, throwflag=<optimized out>)
    at Python/generated_cases.c.h:3748
#9 0x0000506a405a58b9 in PyEval_EvalCode (co=0x30ac6239a170,
    globals=<optimized out>, locals=0x321c2d4f0800) at Python/ceval.c:604
#10 0x0000506a405e3f5c in run_eval_code_obj (
    tstate=tstate@entry=0x506a40889df0 <_PyRuntime+283024>,
    co=co@entry=0x30ac6239a170, globals=globals@entry=0x321c2d4f0800,
    locals=locals@entry=0x321c2d4f0800) at Python/pythonrun.c:1381
#11 0x0000506a405e101b in run_mod (mod=mod@entry=0x5607daf3fe88,
    filename=filename@entry=0x321c2d4f08f0,
    globals=globals@entry=0x321c2d4f0800, locals=locals@entry=0x321c2d4f0800,
    flags=flags@entry=0x7ffd67ad52f8, arena=arena@entry=0x30ac6230fd30,
    interactive_src=0x321c2d511ae0, generate_new_source=0)
    at Python/pythonrun.c:1466
#12 0x0000506a405dc35e in _PyRun_StringFlagsWithName (
    str=str@entry=0x321c2d511400 "from juliacall import Main as jl; [jl.randn(5) for _ in range(10000)]\n", name=name@entry=0x321c2d4f08f0,
    start=start@entry=257, globals=globals@entry=0x321c2d4f0800,
    locals=locals@entry=0x321c2d4f0800, flags=flags@entry=0x7ffd67ad52f8,
    generate_new_source=0) at Python/pythonrun.c:1261

```

We can confirm that prior to that we had a valid Julia object.

```julia
(rr) p jl_(0x588277d1b3c0)
"juliacall.ValueBase"
$6 = void

```

So yay? We found our culprit? For some reason python is smashing the type-tag of a Julia object…

Out of curiosity I kept reverse executing.

```julia
Thread 2 hit Hardware watchpoint 4: *(jl_value_t **) 0x5607dbca7498

Old value = (jl_value_t *) 0x588277d1b3c0 <jl_system_image_data+8141504>
New value = (jl_value_t *) 0x0
0x00006e3638378e6f in jl_genericmemory_ptr_set (m=0x43fd6a5f76d0, i=6939,
    x=0x588277d1b3c0 <jl_system_image_data+8141504>)
    at /home/vchuravy/src/julia-1.11/src/julia.h:1201
1201 jl_atomic_store_release(((_Atomic(jl_value_t*)*)(m_->ptr)) + i, (jl_value_t*)x);

```

```julia
0x00006e3638378e6f in jl_genericmemory_ptr_set (m=0x43fd6a5f76d0, i=6939,
    x=0x588277d1b3c0 <jl_system_image_data+8141504>)
    at /home/vchuravy/src/julia-1.11/src/julia.h:1201
1201 jl_atomic_store_release(((_Atomic(jl_value_t*)*)(m_->ptr)) + i, (jl_value_t*)x);
(rr) bt
#0 0x00006e3638378e6f in jl_genericmemory_ptr_set (m=0x43fd6a5f76d0, i=6939,
    x=0x588277d1b3c0 <jl_system_image_data+8141504>)
    at /home/vchuravy/src/julia-1.11/src/julia.h:1201
#1 0x00006e363837c1fd in jl_idset_put_key (keys=0x43fd6a5f76d0,
    key=0x588277d1b3c0 <jl_system_image_data+8141504>, newidx=0x7ffd67acc4e0)
    at /home/vchuravy/src/julia-1.11/src/idset.c:89
#2 0x00006e36383b029b in jl_as_global_root (
    val=0x588277d1b3c0 <jl_system_image_data+8141504>, insert=1)
    at /home/vchuravy/src/julia-1.11/src/staticdata.c:2547
#3 0x00006e36383af2c9 in jl_root_new_gvars (s=0x7ffd67accb70,
    image=0x7ffd67ace040, external_fns_begin=2748)
    at /home/vchuravy/src/julia-1.11/src/staticdata.c:2283
#4 0x00006e36383b4ee1 in jl_restore_system_image_from_stream_ (
    f=0x7ffd67acdf10, image=0x7ffd67ace040, depmods=0x43fd6a5142f0,
    checksum=18085326892769599201, restored=0x7ffd67acdc50,
    init_order=0x7ffd67acdc58, extext_methods=0x7ffd67acdc60,
    internal_methods=0x7ffd67acdc68, new_ext_cis=0x7ffd67acdc70,
    method_roots_list=0x7ffd67acdc78, ext_targets=0x7ffd67acdc80,
    edges=0x7ffd67acdc88, base=0x7ffd67acdc48, ccallable_list=0x7ffd67acdd90,
    cachesizes=0x7ffd67acdcf0)
    at /home/vchuravy/src/julia-1.11/src/staticdata.c:3532
#5 0x00006e36383b5716 in jl_restore_package_image_from_stream (
    pkgimage_handle=0x5607db723940, f=0x7ffd67acdf10, image=0x7ffd67ace040,
    depmods=0x43fd6a5142f0, completeinfo=0,
    pkgname=0x43fd697287f8 "PythonCall", needs_permalloc=0)
    at /home/vchuravy/src/julia-1.11/src/staticdata.c:3670
#6 0x00006e36383b5bd8 in jl_restore_incremental_from_buf (
    pkgimage_handle=0x5607db723940,
    buf=0x588277557900 <jl_system_image_data> "\373jli\r\n\032\n\f",
    image=0x7ffd67ace040, sz=11933428, depmods=0x43fd6a5142f0, completeinfo=0,
    pkgname=0x43fd697287f8 "PythonCall", needs_permalloc=0)
    at /home/vchuravy/src/julia-1.11/src/staticdata.c:3729
#7 0x00006e36383b6267 in ijl_restore_package_image_from_file (
    fname=0x43fd6aaba138 "/home/vchuravy/.julia/compiled/v1.11/PythonCall/WdXsa_9Ah4Y.so", depmods=0x43fd6a5142f0, completeinfo=0,
    pkgname=0x43fd697287f8 "PythonCall", ignore_native=0)

```

So it is a global variable that we are restoring…  
perhaps

> <https://github.com/JuliaPy/PythonCall.jl/blob/815c0de27a5a175411447dea250e82d52e40f7c5/src/JlWrap/base.jl#L1-L2>

> <https://github.com/JuliaPy/PythonCall.jl/blob/815c0de27a5a175411447dea250e82d52e40f7c5/src/JlWrap/base.jl#L39-L47>

I have no clue what this code is trying to do, but in any case python should not stamp over Julia’s type-tag.

---

_[View the full topic](https://discourse.julialang.org/t/plea-for-segfault-assistance-in-pythoncall-jl/130697)._
