Crash with extensions running `inkscape()` function from `inkex.command`
Summary:
Some extensions call another GUI-less Inkscape instance to process an SVG. inkex.command
Python module has special set of functions for this, e.g. inkscape()
or take_snapshot()
.
An example extension is 'Export Layer Slices'. If such an extension calls Inkscape to process an SVG, then the called Inkscape instance crashes and the extension throws ProgramRunError
:
...
File "share/inkscape/extensions/inkex/command.py", line 238, in _call
raise ProgramRunError(program, process.returncode, stderr, stdout, args)
inkex.command.ProgramRunError: Return Code: -6: b"terminate called after throwing an instance of 'Gio::Error'\n"
...
Backtrace of the crash tells not much (click to see the backtrace):
Program terminated with signal SIGABRT, Aborted.
#0 0x00007f4dcd4a164c in ?? () from /usr/lib/libc.so.6
[Current thread is 1 (Thread 0x7f4dc9e85a80 (LWP 417059))]
(gdb) bt
#0 0x00007f4dcd4a164c in () at /usr/lib/libc.so.6
#1 0x00007f4dcd451958 in raise () at /usr/lib/libc.so.6
#2 0x00007f4dcd43b53d in abort () at /usr/lib/libc.so.6
#3 0x00007f4dcd699833 in __gnu_cxx::__verbose_terminate_handler() () at /usr/src/debug/gcc/libstdc++-v3/libsupc++/vterminate.cc:95
#4 0x00007f4dcd6a5cfc in __cxxabiv1::__terminate(void (*)()) (handler=<optimized out>) at /usr/src/debug/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:48
#5 0x00007f4dcd6a5d69 in std::terminate() () at /usr/src/debug/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:58
#6 0x00007f4dcd6a5fcd in __cxxabiv1::__cxa_throw(void*, std::type_info*, void (*)(void*))
(obj=<optimized out>, tinfo=0x7f4dd26d92d8 <typeinfo for Gio::Error>, dest=0x7f4dcf5286d0) at /usr/src/debug/gcc/libstdc++-v3/libsupc++/eh_throw.cc:98
#7 0x00007f4dcf4ee09f in Gio::Error::throw_func(_GError*) () at /usr/lib/libgiomm-2.4.so.1
#8 0x00007f4dcf1d5c68 in Glib::Error::throw_exception(_GError*) () at /usr/lib/libglibmm-2.4.so.1
#9 0x00007f4dcf504bc0 in Gio::Application::register_application() () at /usr/lib/libgiomm-2.4.so.1
#10 0x00007f4dd20c0f89 in InkscapeApplication::InkscapeApplication() (this=this@entry=0x7ffe911b3400) at /usr/include/glibmm-2.4/glibmm/refptr.h:259
#11 0x000055971e851d36 in main(int, char**) (argc=<optimized out>, argv=<optimized out>) at src/inkscape-main.cpp:207
Running Inkscape command (e.g. to export a PNG) from terminal or even from standalone Python script that imports inkscape()
function from inkex.command
module, while another windowed Inkscape instance is active, gives no crash.
Steps to reproduce:
Easiest way to reproduce the crash is to save a file in .xcf
format. I have to warn about another crash that happens if a 'save-as' extension fails to save a file, this crash is easily fixable (see diff below).
- Open Inkscape
- Draw a rectangle
- Go to 'File -> Save As...' and select
GIMP XCF maintaining layers (*.xcf)
as a file type - Optionally choose a folder and a filename
- Click 'Save' (GIMP XCF dialog appears)
- Click 'OK' in the dialog
- (Inkscape hangs for a moment)
- (First crash of the child Inkscape instance occurs here)
- (Message window with the Python traceback appears, reporting about
ProgramRunError
) - Click 'OK' in the message window
- (Second crash. New windows says: 'Inkscape encountered an internal error...')
- Click 'Close'
To get the backtrace of the first crash I used coredumpctl
tool from systemd.
What happened?
First crash is the reason of this issue, so I'm describing it.
Inkscape called Python (as extension) which called another GUI-less instance of Inkscape as a subprocess. This Inkscape instance crashed (SIGABRT) due to some error in
Gio::Application::register_application()
, I believe. Then the Gio::Error
was thrown and the instance terminated. Python extension returned error message.
What should have happened?
Child Inkscape instances should not crash and, as a consequence, extensions should not fail.
Version info
Inkscape 1.3-dev (1fc8021e, 2023-03-09)
The first crash happens only with 1.3-dev. It does not happen with 1.2.
Possible failed 'Save As` crash (second crash) fix:
(click to see the diff)
+++ b/src/document.cpp
@@ -1104,7 +1104,7 @@ void SPDocument::do_change_filename(gchar const *const filename, bool const reba
this->document_base = new_document_base;
this->document_filename = new_document_filename;
- this->filename_set_signal.emit(this->document_filename);
+ this->filename_set_signal.emit(this->document_name);
(MR coming soon:)