InteractiveHtmlBom icon indicating copy to clipboard operation
InteractiveHtmlBom copied to clipboard

Segmentation fault

Open sborshch opened this issue 1 month ago • 12 comments

Got segmentation fault on almost any pcb. Here is simple board to reproduce:

bom_fail_kicad_pcb.zip

command line : python3 ~/opt/kicad/share/kicad/plugins/InteractiveHtmlBom/InteractiveHtmlBom/generate_interactive_bom.py --hide-silkscreen --checkboxes "" --bom-view top-bottom --layer-view F --dest-dir . --name-format %f_bom --sort-order DD,DA,U,VT,VD,A,R,C,L,FB,~,ZQ,FU,JMP,JP,XP,XS --show-fabrication --include-tracks --netlist-file filename.net filename.kicad_pcb

sborshch avatar Dec 03 '25 07:12 sborshch

Based on your path, you are on linux and you have a custom install of kicad. Most likely you don't have python setup correctly to pick up kicad's libraries from custom paths. Any reason why you are not using a system package for kicad?

qu1ck avatar Dec 03 '25 09:12 qu1ck

Reason is that I'm using most recent version of kicad (git head). kicad itself is working properly. And InteractiveHtmlBom was working correctly at least some time ago (in the end of April). No changes in python setup or library paths was made since that time. Why InteractiveHtmlBom even need access to libraries, while all components info already exist in pcb file? What did you mean by "setup python correctly"? Anyway segmentation fault is not the best way to inform user about incorrect setup.

sborshch avatar Dec 03 '25 10:12 sborshch

What did you mean by "setup python correctly"?

You need to have correct LD_LIBRARY_PATH and PYTHON_PATH env vars so that python loads correct version of pcbnew.py and pcbnew.so for your nightly compile of kicad.

Anyway segmentation fault is not the best way to inform user about incorrect setup.

It is not in my control, by it's nature python bindings to kicad's internal interface can crash python process itself (segfault you are seeing is exactly that), nothing I can do about it from python code.

And InteractiveHtmlBom was working correctly at least some time ago (in the end of April).

If you have a normal (stable) install of kicad as well as the nightly then It's entirely possible that incorrectly setup python was picking up libs from stable and it just happened to work because at that time nightly has not diverged in binary interface from the stable. But now more changes happened and the mismatch is causing the crash.

qu1ck avatar Dec 03 '25 10:12 qu1ck

No, I never had a stable kicad version installed. I have and had the only one (last) version built from sources, the only one pcbnew.py file and pcbnew.so symlink in installation path and symlinks to those pcbnew.py and _pcbnew.so from /usr/lib/python3/dist-packages. The only difference I noticed is that there no share/kicad/plugins/__pycache__ directory in install location and pcbnew.cpython-312.pyc file within anymore, but there is no any messages about it in installation log, so I suppose it is desired difference.

And, yes, LD_LIBRARY_PATH and PYTHON_PATH is empty.

sborshch avatar Dec 03 '25 10:12 sborshch

more digging: <install_path>/share/kicad/plugins/__pycache__ directory and pcbnew.cpython-312.pyc within is created at first kicad run after build. So I restored symlink to it from /usr/lib/python3/dist-packages/__pycache__. Nothing changed. I checked that there is the only one pcbnew.py file and that all _pcbnew.so symlinks points to the same _pcbnew.kiface file. Following https://stackoverflow.com/a/67572451 i inserted import logging (just module name print) into generate_interactive_bom.py and got the following ouput:

...
shutil
Loading a1335_spi.kicad_pcb
kicad
...
pcbnew
...
_pcbnew
...
kicad_extra
...
pcbnew
...
13:34:40: Debug: Adding duplicate image handler for 'PNG file'
13:34:40: Debug: Adding duplicate image handler for 'JPEG file'
13:34:40: Debug: Adding duplicate image handler for 'TIFF file'
13:34:40: Debug: Adding duplicate image handler for 'GIF file'
13:34:40: Debug: Adding duplicate image handler for 'PNM file'
13:34:40: Debug: Adding duplicate image handler for 'PCX file'
13:34:40: Debug: Adding duplicate image handler for 'IFF file'
13:34:40: Debug: Adding duplicate image handler for 'Windows icon file'
13:34:40: Debug: Adding duplicate image handler for 'Windows cursor file'
13:34:40: Debug: Adding duplicate image handler for 'Windows animated cursor file'
13:34:40: Debug: Adding duplicate image handler for 'TGA file'
13:34:40: Debug: Adding duplicate image handler for 'XPM file'
swig_runtime_data4
math
errors
time
time
swig_runtime_data4
swig_runtime_data4
swig_runtime_data4
45165 Segmentation fault      (core dumped) python3 ~/opt/kicad/share/kicad/plugins/InteractiveHtmlBom/InteractiveHtmlBom/generate_interactive_bom.py --hide-silkscreen --checkboxes "" --bom-view top-bottom --layer-view F --dest-dir . --name-format %f_bom --sort-order DD,DA,U,VT,VD,A,R,C,L,FB,~,ZQ,FU,JMP,JP,XP,XS --show-fabrication --include-tracks --netlist-file a1335_spi.net a1335_spi.kicad_pcb

So, it seems like pcbnew.py and _pcbnew.so was resolved correctly despite of empty LD_LIBRARY_PATH and PYTHON_PATH.

sborshch avatar Dec 03 '25 11:12 sborshch

You can completely ignore __pycache__ dirs, python manages them automatically.

So it sounds like you have symlinks setup in system lib dirs so that libraries are found and something else is going on.

First check if plugin works from kicad's UI. Second try to run python command from gdb and look at the stack trace after segfault. Bonus points if you compile kicad with debug symbols for that.

qu1ck avatar Dec 03 '25 21:12 qu1ck

First check if plugin works from kicad's UI.

Did not find how to do it yet.

Second try to run python command from gdb and look at the stack trace after segfault. Bonus points if you compile kicad with debug symbols for that.

Thread 1 "python" received signal SIGSEGV, Segmentation fault.
0x00007fffe525edd3 in KIGFX::GAL::computeWorldScale (this=0x7fffffffd4a0) at /home/serzh/build/kicad/sources/include/gal/graphics_abstraction_layer.h:1048
1048	        if( Pgm().GetCommonSettings() )
(gdb) backtrace

#0  0x00007fffe545edd3 in KIGFX::GAL::computeWorldScale (this=0x7fffffffd4b0) at /home/serzh/build/kicad/sources/include/gal/graphics_abstraction_layer.h:1048
#1  0x00007fffe545d18a in KIGFX::GAL::GAL (this=0x7fffffffd4b0, aDisplayOptions=...) at /home/serzh/build/kicad/sources/common/gal/graphics_abstraction_layer.cpp:71
#2  0x00007fffd4ffb2c4 in CALLBACK_GAL::CALLBACK_GAL(KIGFX::GAL_DISPLAY_OPTIONS&, std::function<void (VECTOR2<int> const&, VECTOR2<int> const&)>, std::function<void (SHAPE_LINE_CHAIN const&)>)
    (this=0x7fffffffd4b0, aDisplayOptions=..., aStrokeCallback=..., aOutlineCallback=...) at /home/serzh/build/kicad/sources/include/callback_gal.h:52
#3  0x00007fffd657f98a in EDA_TEXT::GetEffectiveTextShape (this=0x167b8f0, aTriangulate=false, aBBox=..., aAngle=...) at /home/serzh/build/kicad/sources/common/eda_text.cpp:1201
#4  0x00007fffd54bedb1 in _wrap_EDA_TEXT_GetEffectiveTextShape__SWIG_2 (self=0x7fffee4e1cb0, nobjs=2, swig_obj=0x7fffffffd950) at /home/serzh/build/kicad/build/pcbnew/pcbnew_wrap.cxx:35595
#5  0x00007fffd54bf1b4 in _wrap_EDA_TEXT_GetEffectiveTextShape (self=0x7fffee4e1cb0, args=0x7fffe41fef00) at /home/serzh/build/kicad/build/pcbnew/pcbnew_wrap.cxx:35639
#6  0x0000000000581e70 in ??? ()
#7  0x000000000054afac in PyObject_Call ()
#8  0x00000000005db2ca in _PyEval_EvalFrameDefault ()
#9  0x00000000005d571b in PyEval_EvalCode ()
#10 0x00000000006084c2 in ??? ()
#11 0x00000000006b44f3 in ??? ()
#12 0x00000000006b425a in _PyRun_SimpleFileObject ()
#13 0x00000000006b408f in _PyRun_AnyFileObject ()
#14 0x00000000006bc0f5 in Py_RunMain ()
(gdb) backtrace -full 4

#0  0x00007fffe545edd3 in KIGFX::GAL::computeWorldScale (this=0x7fffffffd4b0) at /home/serzh/build/kicad/sources/include/gal/graphics_abstraction_layer.h:1048
#1  0x00007fffe545d18a in KIGFX::GAL::GAL (this=0x7fffffffd4b0, aDisplayOptions=...) at /home/serzh/build/kicad/sources/common/gal/graphics_abstraction_layer.cpp:71
#2  0x00007fffd4ffb2c4 in CALLBACK_GAL::CALLBACK_GAL(KIGFX::GAL_DISPLAY_OPTIONS&, std::function<void (VECTOR2<int> const&, VECTOR2<int> const&)>, std::function<void (SHAPE_LINE_CHAIN const&)>)
    (this=0x7fffffffd4b0, aDisplayOptions=..., aStrokeCallback=..., aOutlineCallback=...) at /home/serzh/build/kicad/sources/include/callback_gal.h:52
#3  0x00007fffd657f98a in EDA_TEXT::GetEffectiveTextShape (this=0x167b8f0, aTriangulate=false, aBBox=..., aAngle=...) at /home/serzh/build/kicad/sources/common/eda_text.cpp:1201
        callback_gal = {<KIGFX::GAL> = {<KIGFX::GAL_DISPLAY_OPTIONS_OBSERVER> = {_vptr.GAL_DISPLAY_OPTIONS_OBSERVER = 0x7fffe572da48 <vtable for KIGFX::GAL+16>}, static MIN_DEPTH = -4096, static MAX_DEPTH = 4095, static GRID_DEPTH = 4094, m_options = @0x7fffffffd390, m_observerLink = {token_ = std::shared_ptr<UTIL::DETAIL::OBSERVABLE_BASE::IMPL> (empty) = {get() = 0x0}, observer_ = 0x0}, m_depthStack = std::stack wrapping: std::deque with 0 elements, m_screenSize = {x = 0, y = 0}, m_worldUnitLength = 3.9370078740157486e-08, m_screenDPI = 91, m_lookAtPoint = {x = 0, y = 0}, m_zoomFactor = 1, m_rotation = 0, m_worldScreenMatrix = {m_data = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}}, m_screenWorldMatrix = {m_data = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}}, m_worldScale = 3.5826771653543313e-06, m_globalFlipX = false, m_globalFlipY = false, m_lineWidth = 1, m_minLineWidth = 1, m_isFillEnabled = false, m_isStrokeEnabled = true, m_fillColor = {r = 0, g = 0, b = 0, a = 0}, m_strokeColor = {r = 1, g = 1, b = 1, a = 1}, m_clearColor = {r = 0, g = 0, b = 0, a = 1}, m_layerDepth = 0, m_depthRange = {x = -4096, y = 4095}, m_gridVisibility = 254, m_gridStyle = (KIGFX::GRID_STYLE::SMALL_CROSS | unknown: 0xfefefefc), m_gridSize = {x = 0, y = 0}, m_gridOrigin = {x = 0, y = 0}, m_gridOffset = {x = 0, y = 0}, m_gridColor = {r = 0, g = 0, b = 0, a = 1}, m_axesColor = {r = 0, g = 0, b = 0, a = 1}, m_axesEnabled = 254, m_gridTick = -16843010, m_gridLineWidth = -1.69473953e+38, m_gridMinSpacing = -16843010, m_isCursorEnabled = 254, m_forceDisplayCursor = 254, m_cursorColor = {r = 0, g = 0, b = 0, a = 1}, m_crossHairMode = (KIGFX::CROSS_HAIR_MODE::FULLSCREEN_DIAGONAL | unknown: 0xfefefefc), m_cursorPosition = {x = 0, y = 0}, m_currentNativeCursor = KICURSOR::DEFAULT, m_attributes = {m_Font = 0x0, m_Halign = GR_TEXT_H_ALIGN_CENTER, m_Valign = GR_TEXT_V_ALIGN_CENTER, m_Angle = {static DEGREES_TO_RADIANS = 0.017453292519943295, m_value = 0}, m_LineSpacing = 1, m_StrokeWidth = 0, m_Italic = false, m_Bold = false, m_Underlined = false, m_Color = {r = 0, g = 0, b = 0, a = 0}, m_Mirrored = false, m_Multiline = true, m_Size = {x = 0, y = 0}, m_KeepUpright = false, m_StoredStrokeWidth = 0}}, m_strokeCallback = {<std::_Maybe_unary_or_binary_function<void, VECTOR2<int> const&, VECTOR2<int> const&>> = {<std::binary_function<VECTOR2<int> const&, VECTOR2<int> const&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0xfefefefefefefefe, _M_const_object = 0xfefefefefefefefe, _M_function_pointer = 0xfefefefefefefef--Type <RET> for more, q to quit, c to continue without paging--c

e, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0xfefefefefefefefe, this adjustment -72340172838076674}, _M_pod_data = '\376' <repeats 16 times>}, _M_manager = 0xfefefefefefefefe}, _M_invoker = 0xfefefefefefefefe}, m_triangleCallback = {<std::_Maybe_unary_or_binary_function<void, VECTOR2<int> const&, VECTOR2<int> const&, VECTOR2<int> const&>> = {<No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0xfefefefefefefefe, _M_const_object = 0xfefefefefefefefe, _M_function_pointer = 0xfefefefefefefefe, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0xfefefefefefefefe, this adjustment -72340172838076674}, _M_pod_data = '\376' <repeats 16 times>}, _M_manager = 0xfefefefefefefefe}, _M_invoker = 0xfefefefefefefefe}, m_outlineCallback = {<std::_Maybe_unary_or_binary_function<void, SHAPE_LINE_CHAIN const&>> = {<std::unary_function<SHAPE_LINE_CHAIN const&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0xfefefefefefefefe, _M_const_object = 0xfefefefefefefefe, _M_function_pointer = 0xfefefefefefefefe, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0xfefefefefefefefe, this adjustment -72340172838076674}, _M_pod_data = '\376' <repeats 16 times>}, _M_manager = 0xfefefefefefefefe}, _M_invoker = 0xfefefefefefefefe}, m_stroke = 254, m_triangulate = 254}
        shape = std::shared_ptr<SHAPE_COMPOUND> (use count 1, weak count 0) = {get() = 0x1702bd0}
        empty_opts = {<UTIL::OBSERVABLE<KIGFX::GAL_DISPLAY_OPTIONS_OBSERVER>> = {<UTIL::DETAIL::OBSERVABLE_BASE> = {impl_ = std::shared_ptr<UTIL::DETAIL::OBSERVABLE_BASE::IMPL> (empty) = {get() = 0x0}}, <No data fields>}, _vptr.GAL_DISPLAY_OPTIONS = 0x7fffd7d9d5a0 <vtable for KIGFX::GAL_DISPLAY_OPTIONS+16>, antialiasing_mode = KIGFX::GAL_ANTIALIASING_MODE::AA_NONE, m_gridStyle = KIGFX::GRID_STYLE::DOTS, m_gridSnapping = KIGFX::GRID_SNAPPING::ALWAYS, m_gridLineWidth = 1, m_gridMinSpacing = 10, m_axesEnabled = false, m_crossHairMode = KIGFX::CROSS_HAIR_MODE::SMALL_CROSS, m_forceDisplayCursor = false, m_scaleFactor = 1}
        font = 0x16ea3d0
        penWidth = 100000

sborshch avatar Dec 04 '25 09:12 sborshch

Well here we go, the crash happens in kicad code and points to a recent change https://gitlab.com/kicad/code/kicad/-/commit/bfe805a221141707f92b823d6cc9ec5f85e02a4b#662070370f1574ef7574fe884f1ea8b25aa54dd3

Do one more test start bare python interpreter and enter following commands:

import pcbnew
pcbnew.LoadBoard("path/to/your/board.kicad_pcb")

I'm pretty sure you will get a crash with this too and you can report that to kicad, along with the stack trace you got.

Did not find how to do it yet.

Just press the plugin button on pcb editor's toolbar. If I understand the code leading to the crash correctly, it should work from GUI.

qu1ck avatar Dec 04 '25 11:12 qu1ck

Do one more test

No crash:

username@hostname:~/projects/xxx/a1335/spi$ python3
Python 3.12.3 (main, Nov  6 2025, 13:44:16) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pcbnew
>>> pcbnew.LoadBoard("./a1335_spi.kicad_pcb")
<pcbnew.BOARD; proxy of <Swig Object of type 'BOARD *' at 0x75ba74f8f2d0> >
>>> 

If I understand the code leading to the crash correctly, it should work from GUI.

Yes, it works.

sborshch avatar Dec 04 '25 12:12 sborshch

I see, it doesnt crash just on load, it needs to try to get text shape. Try this script (update path and reference if you dont have R1)

import pcbnew

pcb_path = "/home/quick/electronics/OSP/HP34401aOLED/hp34401a_oled.kicad_pcb"

board: pcbnew.BOARD = pcbnew.LoadBoard(pcb_path)
fp: pcbnew.FOOTPRINT = board.FindFootprintByReference("R1")
ref: pcbnew.PCB_FIELD = fp.Reference()
txt = ref.GetEffectiveTextShape(False)
print(txt)

It should print out something like <pcbnew.SHAPE_COMPOUND; proxy of <Swig Object of type 'std::shared_ptr< SHAPE_COMPOUND > *' at 0x7f6594ef9170> >

but in your case will likely crash.

qu1ck avatar Dec 04 '25 20:12 qu1ck

Yes, it is!

user@host:~/projects/xxx/a1335/spi$ python3 test.py 
/home/serzh/build/kicad/sources/common/pgm_base.cpp(948): assert "process" failed in Pgm().
Segmentation fault (core dumped)

sborshch avatar Dec 04 '25 21:12 sborshch

And that is something you can take to KiCad issue tracker :)

Post the script, your backtrace from gdb and full kicad version info, that is something they should be able to fix.

You can link the kicad commit I pointed to as a likely suspect.

qu1ck avatar Dec 04 '25 23:12 qu1ck