Closed mandree closed 5 years ago
@Floessie Do you have an idea?
@heckflosse The mutex could be already destroyed or locked while being destroyed. But there is no RT code on the path, so this looks more like a GTK3 problem (or a problem in how we use it somewhere). Don't we have debug facilities for MyMutex
that might shed some light on this?
Yes, as explained in rtgui/threadutils.cc, you can uncomment #define TRACE_MYRWMUTEX 1
to let RT log in stdout all MyMutex operations. If something is used while already freed or in case of deadlock, you'll see where it occurred in the code.
Initial attempts have not helped me find misuse of mutexes.
This is how lldb40 sees the crashing thread on exit with RawTherapee 5.1 in a different place, compiled in Debug mode on FreeBSD 10.3 amd64 (requisites are a bit newer).
* thread #1, stop reason = signal SIGABRT
* frame #0: 0x00000008068bb39a libc.so.7`__sys_thr_kill + 10
frame #1: 0x00000008068bb386 libc.so.7`raise + 38
frame #2: 0x00000008068bb309 libc.so.7`abort + 73
frame #3: 0x00000008036f254e libglibmm-2.4.so.1
frame #4: 0x000000080370cd9d libglibmm-2.4.so.1`Glib::ObjectBase::~ObjectBase() + 173
frame #5: 0x00000008046b01db libgdkmm-3.0.so.1`virtual thunk to Gdk::Pixbuf::~Pixbuf() + 75
frame #6: 0x0000000802a6fa93 libglib-2.0.so.0`g_datalist_clear + 131
frame #7: 0x000000080280ba9a libgobject-2.0.so.0`g_object_unref + 474
frame #8: rawtherapee`Glib::RefPtr<Gdk::Pixbuf>::~RefPtr(this=0x000000081a72d138) at refptr.h:268
frame #9: rawtherapee`std::__1::pair<Glib::ustring const, Glib::RefPtr<Gdk::Pixbuf> >::~pair(this=0x000000081a72d120) at utility:248
frame #10: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(std::__1::__tree_node<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, void*>*) [inlined] _ZNSt3__112__value_typeIN4Glib7ustringENS1_6RefPtrIN3Gdk6PixbufEEEED4Ev(this=0x000000081a72d120) at map:617
frame #11: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(std::__1::__tree_node<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, void*>*) [inlined] void std::__1::allocator_traits<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, void*> > >::__destroy<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > >(__p=0x000000081a72d120, (null)=0x00000000014b5e38, (null)=std::__1::false_type @ 0x00007fffffffe3e6) at memory:1589
frame #12: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(std::__1::__tree_node<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, void*>*) [inlined] void std::__1::allocator_traits<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, void*> > >::destroy<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > >(__p=0x000000081a72d120, __a=0x00000000014b5e38) at memory:1487
frame #13: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014b5e30, __nd=0x000000081a72d100) at __tree:1445
frame #14: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014b5e30, __nd=0x0000000813ca9580) at __tree:1443
frame #15: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014b5e30, __nd=0x0000000813ca9440) at __tree:1443
frame #16: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014b5e30, __nd=0x0000000813ca96c0) at __tree:1443
frame #17: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014b5e30, __nd=0x00000008176968c0) at __tree:1442
frame #18: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014b5e30, __nd=0x0000000813d4f3c0) at __tree:1443
frame #19: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014b5e30, __nd=0x00000008129aa740) at __tree:1442
frame #20: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::~__tree(this=0x00000000014b5e30) at __tree:1433
frame #21: rawtherapee`std::__1::map<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf>, std::__1::less<Glib::ustring>, std::__1::allocator<std::__1::pair<Glib::ustring const, Glib::RefPtr<Gdk::Pixbuf> > > >::~map(this=0x00000000014b5e30 size=195) at map:783
frame #22: 0x000000080691a210 libc.so.7`__cxa_finalize + 320
frame #23: 0x00000008068bb29c libc.so.7`exit + 28
frame #24: 0x00000000005597c6 rawtherapee`_start + 374
Requisite packages installed:
atk-2.24.0 gdk-pixbuf2-2.36.6 libiptcdata-1.0.4_2
atkmm-2.24.2 gettext-runtime-0.19.8.1_1 libsigc++-2.10.0
cairo-1.14.8,2 glib-2.50.2_2,1 libxml++-2.34.2,1
cairomm-1.12.2 glibmm-2.50.1,1 libxml2-2.9.4
desktop-file-utils-0.23 gtk-update-icon-cache-2.24.29 openmp-4.0.0_2
expat-2.2.0_1 gtk3-3.22.15 pango-1.40.4
fftw3-3.3.6.p2 gtkmm30-3.22.0 pangomm-2.40.1
fftw3-float-3.3.6.p2 jpeg-turbo-1.5.1 png-1.6.29
fontconfig-2.12.1,1 lcms2-2.8 tiff-4.0.7_1
freetype2-2.7.1 libcanberra-0.30_4
gcc5-5.4.0_2 libcanberra-gtk3-0.30_4
@Floessie @agriggio Do you have an idea about the reason for the SIGABRT? For me it looks like it could be caused be the pixbufCache
in rtimage.cc. But I'm just shooting into the dark...
I've recompiled the libs with debug information as well, and this is what I get. I have also tried recompiling everything with clang-4.0 in c++14 mode (instead of GCC 5.4, as used below) because all the other libs are compiled with clang-3.4.1, but that doesn't change anything.
* thread #1, stop reason = signal SIGABRT
* frame #0: 0x0000000806c4639a libc.so.7`__sys_thr_kill + 10
frame #1: 0x0000000806c46386 libc.so.7`raise + 38
frame #2: 0x0000000806c46309 libc.so.7`abort + 73
frame #3: 0x00000008038e3bb6 libglibmm-2.4.so.1`__clang_call_terminate + 22
frame #4: libglibmm-2.4.so.1`Glib::ObjectBase::~ObjectBase(this=0x000000081af10f90, vtt=0x0000000804c57758) at objectbase.cc:161
frame #5: libgdkmm-3.0.so.1`Gdk::Pixbuf::~Pixbuf(this=0x000000081af10f80) at pixbuf.cc:376
frame #6: libgdkmm-3.0.so.1`Gdk::Pixbuf::~Pixbuf(this=0x000000081af10f80) at pixbuf.cc:376
frame #7: libgdkmm-3.0.so.1`virtual thunk to Gdk::Pixbuf::~Pixbuf(this=0x000000081af10f90) at pixbuf.cc:376
frame #8: libglibmm-2.4.so.1`Glib::ObjectBase::destroy_notify_(this=0x000000081af10f90) at objectbase.cc:307
frame #9: libglibmm-2.4.so.1`Glib::ObjectBase::destroy_notify_callback_(data=0x000000081af10f90) at objectbase.cc:284
frame #10: libglib-2.0.so.0`g_datalist_clear(datalist=0x000000081ae7fcd0) at gdataset.c:273
frame #11: libgobject-2.0.so.0`g_object_finalize(object=0x000000081ae7fcc0) at gobject.c:1044
frame #12: libgdk_pixbuf-2.0.so.0`gdk_pixbuf_finalize(object=0x000000081ae7fcc0) at gdk-pixbuf.c:277
frame #13: libgobject-2.0.so.0`g_object_unref(_object=0x000000081ae7fcc0) at gobject.c:3185
frame #14: libglibmm-2.4.so.1`Glib::ObjectBase::unreference(this=0x000000081af10f90) const at objectbase.cc:200
frame #15: rawtherapee`Glib::RefPtr<Gdk::Pixbuf>::~RefPtr(this=0x000000081af250b8) at refptr.h:268
frame #16: rawtherapee`std::__1::pair<Glib::ustring const, Glib::RefPtr<Gdk::Pixbuf> >::~pair(this=0x000000081af250a0) at utility:248
frame #17: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(std::__1::__tree_node<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, void*>*) [inlined] _ZNSt3__112__value_typeIN4Glib7ustringENS1_6RefPtrIN3Gdk6PixbufEEEED4Ev(this=0x000000081af250a0) at map:617
frame #18: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(std::__1::__tree_node<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, void*>*) [inlined] void std::__1::allocator_traits<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, void*> > >::__destroy<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > >(__p=0x000000081af250a0, (null)=0x00000000014c2c38, (null)=std::__1::false_type @ 0x00007fffffffe3d6) at memory:1589
frame #19: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(std::__1::__tree_node<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, void*>*) [inlined] void std::__1::allocator_traits<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, void*> > >::destroy<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > >(__p=0x000000081af250a0, __a=0x00000000014c2c38) at memory:1487
frame #20: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014c2c30, __nd=0x000000081af25080) at __tree:1445
frame #21: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014c2c30, __nd=0x00000008148cc540) at __tree:1443
frame #22: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014c2c30, __nd=0x00000008148cc400) at __tree:1443
frame #23: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014c2c30, __nd=0x00000008148cc680) at __tree:1443
frame #24: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014c2c30, __nd=0x0000000818285840) at __tree:1442
frame #25: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014c2c30, __nd=0x0000000816ff7340) at __tree:1443
frame #26: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::destroy(this=0x00000000014c2c30, __nd=0x00000008135a0700) at __tree:1442
frame #27: rawtherapee`std::__1::__tree<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::__map_value_compare<Glib::ustring, std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> >, std::__1::less<Glib::ustring>, true>, std::__1::allocator<std::__1::__value_type<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf> > > >::~__tree(this=0x00000000014c2c30) at __tree:1433
frame #28: rawtherapee`std::__1::map<Glib::ustring, Glib::RefPtr<Gdk::Pixbuf>, std::__1::less<Glib::ustring>, std::__1::allocator<std::__1::pair<Glib::ustring const, Glib::RefPtr<Gdk::Pixbuf> > > >::~map(this=0x00000000014c2c30 size=195) at map:783
frame #29: 0x0000000806ca5210 libc.so.7`__cxa_finalize + 320
frame #30: 0x0000000806c4629c libc.so.7`exit + 28
frame #31: 0x0000000000565a46 rawtherapee`_start + 374
Frame #4 source code detail:
141 ObjectBase::~ObjectBase() noexcept
142 {
143 // Normally, gobject_ should always be 0 at this point, because:
[...]
157 // Just a precaution. Unless a derived class's ctor has thrown an exception,
158 // 'this' should have been erased from extra_object_base_data by
159 // Glib::Object's constructor.
160 {
161 std::lock_guard<std::mutex> lock(extra_object_base_data_mutex);
162 extra_object_base_data.erase(this);
163 }
These are the requisite package versions:
atk-2.24.0 gdk-pixbuf2-2.36.6 libiptcdata-1.0.4_2
atkmm-2.24.2 gettext-runtime-0.19.8.1_1 libsigc++-2.10.0
cairo-1.14.8,2 glib-2.50.2_2,1 libxml++-2.34.2,1
cairomm-1.12.2 glibmm-2.50.1,1 libxml2-2.9.4
desktop-file-utils-0.23 gtk-update-icon-cache-2.24.29 openmp-4.0.0_2
expat-2.2.0_1 gtk3-3.22.15 pango-1.40.4
fftw3-3.3.6.p2 gtkmm30-3.22.0 pangomm-2.40.1
fftw3-float-3.3.6.p2 jpeg-turbo-1.5.1 png-1.6.29
fontconfig-2.12.1,1 lcms2-2.8 tiff-4.0.7_1
freetype2-2.7.1 libcanberra-0.30_4
gcc5-5.4.0_2 libcanberra-gtk3-0.30_4
@heckflosse Yes, that's the only place where a static std::map<>
holds a Glib::RefPtr<Gdk::Pixbuf>
. One should move that to a singleton PixbufStore
and deal with it at least in the d'tor and perhaps even better a bit earlier on shutdown. Maybe Alberto has an even better idea...
It's a pity, we only see it on FreeBSD.
If I hack glibmm and wrap line 161 in a try {} catch() {} block, I get this:
(rawtherapee:32513): glibmm-ERROR **:
unhandled exception (type std::exception) in signal handler:
what: mutex lock failed: Invalid argument
Trace/BPT trap
So, by any chance, is there anything in the thread arrangement that could glibmm's extra_object_base_data_mutex to have been destroyed before the last ObjectBase is?
@Floessie 's proposal apparently has the same underlying thought - moving the Pixbuf into a singleton PixbufStore and dealing with it explicitly would change the destruction order.
Assuming FreeBSD implements the Mutex in a similar vein to pthread mutexes, for the latter there is documentation as this:
ERRORS
The pthread_mutex_lock() function will fail if:
[EINVAL] The value specified by mutex is invalid.
which would happen, for instance, through pthread_mutex_destroy().
This issue persists in RawTherapee 5.5 on FreeBSD 12.0 amd64 (= x86_64).
@mandree I'd like to tackle that bug, but need assistance, as I'm completely unfamiliar with (Free)BSD. What I need is a Qemu 2.8 AMD64 VM on an at least 5GB virtual qcow2 image. Either you provide me with an image or I set it up with your help (I'd prefer to set it up myself). For the latter I need kind of a TODO list on how to install the basic system and how to find and install the packages RT depends on. And I need an SSH client and the Geany editor.
With such a list and me trying to follow it, we could even extend Rawpedia with a "Compiling / BSDs" page.
Best, Flössie
Update: I'm downloading FreeBSD 12.0 amd64 dvd1 right now. I'll ping you back in case of installation troubles within the next days.
@mandree So, I've got the basic system up, installed xorg, the video-vmware driver, and XFCE, but when I run startx
I get a psychedelic pattern and the VM is stuck. Any hints?
Is vmware driver actually tries to load by Xorg ? Probably it needs a hint in /usr/local/etc/X11/xorg.conf.d/ Try to drop a conf file with
Section "Device"
Identifier "Card0"
Driver "vmware"
EndSection
@Floessie I normally use VirtualBox to host my FreeBSD guests, not qemu, and in case video is difficult but you have a running Linux installation with X11 or Xorg proper (not Wayland), just ssh -AX my_freebsd_machine
from the Linux computer and don't run X11 in the guest machine.
The one thing is that you'd probably also need to build all the requisites in debug versions (default is stripped release build), for that I'd put WITH_DEBUG=yes into /etc/make.conf and rebuild everything. The quick easy way to do that is pkg install -y portmaster
(which is a shell script) and then portmaster -fr rawtherapee
, before starting to debug.
We can try to use IRC for on-line support if you want, or negotiate some kind of instant messaging.
@abishai @mandree Thanks for the tips. I'll give it a try after Christmas. Thing is, the guest system completely freezes, and even sending a ctrl-alt-f2 won't give me a login to inspect. I found an issue that might be related. But the ssh way is sure viable.
If that all takes too much time, I'll convert the PixbufStore
into a proper singleton and let you test it. :wink:
Have a nice Christmas time, Flössie
@Floessie try VirtualBox...
@abishai No luck with the xorg.conf: "Module 'vmware' not found" although I installed xf86-video-vmware
through pkg install
.
@mandree No, I don't want to taint my system.
I've created a new branch for you to test.
Best, Flössie
@Floessie if VirtualBox doesn't cut the mustard for you, I'll just say that I'm also debugging with a ssh -X :-)
If the intention of the pixbuf-cache-revision branch was to fix the SIGABRT-on-exit, then we're not quite there:
Thread 1 received signal SIGABRT, Aborted.
thr_kill () at thr_kill.S:3
3 RSYSCALL(thr_kill)
(gdb) thread apply all bt full
Thread 3 (LWP 101447 of process 80234):
#0 0x0000000801d9b66c in _umtx_op_err () at /usr/src/lib/libthr/arch/amd64/amd64/_umtx_op_err.S:37
#1 0x0000000801d8f731 in _thr_umtx_timedwait_uint (mtx=0x807929020, id=<optimized out>, clockid=<optimized out>, abstime=<optimized out>, shared=<optimized out>) at /usr/src/lib/libthr/thread/thr_umtx.c:236
tm_p = 0xe1e
tm_size = Python Exception <class 'gdb.MemoryError'> Cannot access memory at address 0x18:
#2 0x0000000801d99388 in cond_wait_user (abstime=0x7fffdfdfbe80, cancel=1, cvp=<optimized out>, mp=<optimized out>) at /usr/src/lib/libthr/thread/thr_cond.c:307
curthread = 0x8111a5100
deferred = Python Exception <class 'gdb.MemoryError'> Cannot access memory at address 0x0:
#3 0x0000000801d99388 in cond_wait_common (cond=<optimized out>, mutex=<optimized out>, abstime=0x7fffdfdfbe80, cancel=1) at /usr/src/lib/libthr/thread/thr_cond.c:367
curthread = <optimized out>
cvp = 0x809979ee0
mp = 0x8112d8cc0
error = <optimized out>
#4 0x0000000802199572 in g_cond_wait_until (cond=0x80fb37348, mutex=0x80fb37340, end_time=3614624739) at gthread-posix.c:908
ts = {tv_sec = 3614, tv_nsec = 624739000}
status = 8
#5 0x00000008020ecb68 in g_async_queue_pop_intern_unlocked (queue=0x80fb37340, wait=1, end_time=3614624739) at gasyncqueue.c:422
retval = 0x7fffdfdfbee0
#6 0x00000008020ecda8 in g_async_queue_timeout_pop (queue=0x80fb37340, timeout=15000000) at gasyncqueue.c:543
end_time = 3614624739
retval = 0x8111a53b0
#7 0x000000080216c2b2 in g_thread_pool_wait_for_new_pool () at gthreadpool.c:167
pool = 0x808243240
local_wakeup_thread_serial = 0
local_max_unused_threads = 2
local_max_idle_time = 15000
last_wakeup_thread_serial = 0
have_relayed_thread_marker = 0
#8 0x000000080216c117 in g_thread_pool_thread_proxy (data=0x8112d8ba0) at gthreadpool.c:364
free_pool = 0
task = 0x0
pool = 0x80b266980
#9 0x000000080216aaed in g_thread_proxy (data=0x8113c3d90) at gthread.c:784
thread = 0x8113c3d90
#10 0x0000000801d8d776 in thread_start (curthread=0x8111a5100) at /usr/src/lib/libthr/thread/thr_create.c:292
set = {__bits = {0, 0, 0, 0}}
#11 0x0000000000000000 in ()
Thread 2 (LWP 101446 of process 80234):
#0 0x000000080342326a in _poll () at _poll.S:3
#1 0x0000000801d90296 in __thr_poll (fds=0x8079d55e0, nfds=2, timeout=-1) at /usr/src/lib/libthr/thread/thr_syscalls.c:338
curthread = 0x8078c4c00
ret = <optimized out>
#2 0x0000000802147621 in g_poll (fds=0x8079d55e0, nfds=2, timeout=-1) at gpoll.c:124
#3 0x0000000802133baa in g_main_context_poll (context=0x807608480, timeout=-1, priority=2147483647, fds=0x8079d55e0, n_fds=2) at gmain.c:4203
ret = 0
errsv = 0
poll_func = 0x802147600 <g_poll>
#4 0x0000000802131a15 in g_main_context_iterate (context=0x807608480, block=1, dispatch=1, self=0x80771c370) at gmain.c:3897
max_priority = 2147483647
timeout = -1
some_ready = 8
nfds = 2
allocated_nfds = 2
fds = 0x8079d55e0
#5 0x0000000802131ab3 in g_main_context_iteration (context=0x807608480, may_block=1) at gmain.c:3963
retval = 1
#6 0x000000080213344d in glib_worker_main (data=0x0) at gmain.c:5772
#7 0x000000080216aaed in g_thread_proxy (data=0x80771c370) at gthread.c:784
thread = 0x80771c370
#8 0x0000000801d8d776 in thread_start (curthread=0x8078c4c00) at /usr/src/lib/libthr/thread/thr_create.c:292
set = {__bits = {0, 0, 0, 0}}
#9 0x0000000000000000 in ()
Thread 1 (LWP 100434 of process 80234):
#0 0x000000080347f41a in thr_kill () at thr_kill.S:3
#1 0x000000080347d804 in __raise (s=6) at /usr/src/lib/libc/gen/raise.c:52
id = 100434
#2 0x00000008033f0099 in abort () at /usr/src/lib/libc/stdlib/abort.c:67
act = <optimized out>
#3 0x000000080264e30f in () at /usr/local/lib/libglibmm-2.4.so.1
#4 0x00000008026a184b in Glib::ObjectBase::~ObjectBase() (this=0x806faaed0, vtt=0x8027bd6e8 <VTT for Gdk::Pixbuf+72>) at objectbase.cc:160
lock = {__m_ = @0x8026d3210}
#5 0x000000080279e618 in Gdk::Pixbuf::~Pixbuf() (this=0x806faaec0) at pixbuf.cc:376
#6 0x000000080279e689 in Gdk::Pixbuf::~Pixbuf() (this=0x806faaec0) at pixbuf.cc:376
#7 0x00000008026a19e3 in Glib::ObjectBase::destroy_notify_() (this=0x806faaed0) at objectbase.cc:306
#8 0x00000008026a194c in Glib::ObjectBase::destroy_notify_callback_(void*) (data=0x806faaed0) at objectbase.cc:283
cppObject = 0x806faaed0
#9 0x00000008021065f5 in g_datalist_clear (datalist=0x8077a7df0) at gdataset.c:273
data = 0x806faaf00
i = 1
#10 0x000000080202246e in g_object_finalize (object=0x8077a7de0 [GdkPixbuf]) at gobject.c:1062
#11 0x000000080201b440 in g_object_unref (_object=0x8077a7de0) at gobject.c:3340
weak_locations = 0x0
object = 0x8077a7de0 [GdkPixbuf]
old_ref = 1
#12 0x00000008026a18e9 in Glib::ObjectBase::unreference() const (this=0x806faaed0) at objectbase.cc:199
#13 0x0000000000528c5f in Glib::RefPtr<Gdk::Pixbuf>::~RefPtr() (this=0x12634b0 <MyExpander::closedPBuf>) at /usr/local/include/glibmm-2.4/glibmm/refptr.h:273
#14 0x0000000803460081 in __cxa_finalize (dso=0x0) at /usr/src/lib/libc/stdlib/atexit.c:237
phdr_info = {dlpi_addr = 140737488345424, dlpi_name = 0x80124b04d <_rtld_bind_start+45> "H\211D$`A[AZAYAX_^YZX\235H\215d$\020\303f\220H\215\005\241\242\001", dlpi_phdr = 0x0, dlpi_phnum = 53864, dlpi_adds = 0, dlpi_subs = 165, dlpi_tls_modid = 0, dlpi_tls_data = 0x2}
has_phdr = 0
p = <optimized out>
fn = {fn_type = 2, fn_ptr = {std_func = 0x528c20 <Glib::RefPtr<Gdk::Pixbuf>::~RefPtr()>, cxa_func = 0x528c20 <Glib::RefPtr<Gdk::Pixbuf>::~RefPtr()>}, fn_arg = 0x12634b0 <MyExpander::closedPBuf>, fn_dso = <synthetic pointer>}
#15 0x00000008033efce1 in exit (status=0) at /usr/src/lib/libc/stdlib/exit.c:74
#16 0x00000000004fb122 in _start (ap=<optimized out>, cleanup=<optimized out>) at /usr/src/lib/csu/amd64/crt1.c:76
argc = <optimized out>
env = 0x7fffffffd9d8
argv = 0x7fffffffd9c8
And compilation with mutex tracing, without OpenMP, and with a try/catch block in gtkmm added wrapping line 160 yields this (this is only showing after I click the window's close button):
0x80778b200:../rtgui/filebrowser.cc:671: Acquiring MyWriterLock...
0x80778b200:../rtgui/filebrowser.cc:671: MyWriterLock is now locked, reader count is 0, writer count is 1.
0x80778b200:../rtgui/filebrowser.cc:675: Releasing MyWriterLock...
0x80778b200:../rtgui/filebrowser.cc:675: MyWriterLock is now unlocked, reader count is 0, writer count is 0.
0x80778b200:../rtgui/filebrowser.cc:1955: Acquiring MyReaderLock...
0x80778b200:../rtgui/filebrowser.cc:1955: MyReaderLock is now locked, reader count is 1, writer count is 1.
0x80778b200:../rtgui/threadutils.h:282: Releasing MyReaderLock...
0x80778b200:../rtgui/threadutils.h:282: MyReaderLock is now unlocked, reader count is 0, writer count is 0.
0x80778b200:../rtgui/filebrowser.cc:679: Acquiring MyWriterLock...
0x80778b200:../rtgui/filebrowser.cc:679: MyWriterLock is now locked, reader count is 0, writer count is 1.
0x80778b200:../rtgui/threadutils.h:289: Releasing MyWriterLock...
0x80778b200:../rtgui/threadutils.h:289: MyWriterLock is now unlocked, reader count is 0, writer count is 0.
0x80778b200:../rtgui/batchqueue.cc:112: Acquiring MyWriterLock...
0x80778b200:../rtgui/batchqueue.cc:112: MyWriterLock is now locked, reader count is 0, writer count is 1.
0x80778b200:../rtgui/threadutils.h:289: Releasing MyWriterLock...
0x80778b200:../rtgui/threadutils.h:289: MyWriterLock is now unlocked, reader count is 0, writer count is 0.
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
objectbase.cc:166: caught std::exception: mutex lock failed: Invalid argument
[LWP 100683 of process 6625 exited]
[LWP 100684 of process 6625 exited]
[Inferior 1 (process 6625) exited normally]
The relevant glib/glibmm/objectbase.cc
gets an #include <iostream>
added on top and then the code shown below in the ObjectBase::~ObjectBase() noexcept {}
destructor prevents the abort. I am not so sure what business a destructor has acquiring a mutex(*) but anyways. The original code is just the lock() and extra_object_base_data.erase(). Further inspection (not logged here) reveals that it's always the same native_handle() for extra_object_base_data_mutex.
(*) EDIT: ...what business a destructor has acquiring a mutex and letting the exception escape...
{
try {
std::lock_guard<std::mutex> lock(extra_object_base_data_mutex);
extra_object_base_data.erase(this);
}
catch (std::exception& ex) {
std::cerr << __FILE__ << ":" << __LINE__ << ": caught std::exception: " << ex.what() << std::endl;
}
catch (...) {
std::cerr << "Caught unknown exception." << std::endl;
}
}
if (GObject* const gobject = gobject_)
[...]
I made an experiment and inserted std::quick_exit(ret);
at the very end of main.cc's main()
, which seems to fix the crash because it waives the destruction of MyExpander::closedPBuf
(among others).
How dangerous would it be to forgo the regular destruction, in order to ultimately let the kernel do more of the cleanups? Yes it's leaky, but this is Unix...
Is there anything important/precious to be done in the exit handlers?
@mandree With Qemu 3.1 I was able to install FreeBSD and RT and to reproduce the problem. The problem (as you already noticed) is that something in GTK/GLIB is destroyed prior to the __cxa_atexit()
dance. If anyone has a hint (maybe @Hombre57) that would be more than welcome. Fact is, Glib::RefPtr
s destroyed through __cxa_atexit
(these are the static or indirectly static ones) abort on FreeBSD.
Do other glibmm applications show similar errors on FreeBSD? Or is it just us using static Glib::RefPtr
s?
Here's a patch for the pixbuf-cache-revision
branch that makes an RT without images in the file browser or editor exit sanely:
diff --git a/rtgui/cursormanager.cc b/rtgui/cursormanager.cc
index 34efbcac8..b558ab2a9 100644
--- a/rtgui/cursormanager.cc
+++ b/rtgui/cursormanager.cc
@@ -79,6 +79,29 @@ void CursorManager::init (Glib::RefPtr<Gdk::Window> mainWindow)
window = mainWindow;
}
+void CursorManager::cleanup()
+{
+ cAdd.reset();
+ cAddPicker.reset();
+ cCropDraw.reset();
+ cCrosshair.reset();
+ cHandClosed.reset();
+ cHandOpen.reset();
+ cEmpty.reset();
+ cMoveBL.reset();
+ cMoveBR.reset();
+ cMoveL.reset();
+ cMoveR.reset();
+ cMoveTL.reset();
+ cMoveTR.reset();
+ cMoveX.reset();
+ cMoveY.reset();
+ cMoveXY.reset();
+ cRotate.reset();
+ cWB.reset();
+ cWait.reset();
+}
+
/* Set the cursor of the given window */
void CursorManager::setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape shape)
{
diff --git a/rtgui/cursormanager.h b/rtgui/cursormanager.h
index 7d3f068b2..cc52af48f 100644
--- a/rtgui/cursormanager.h
+++ b/rtgui/cursormanager.h
@@ -82,6 +82,7 @@ private:
public:
void init (Glib::RefPtr<Gdk::Window> mainWindow);
+ void cleanup();
static void setWidgetCursor (Glib::RefPtr<Gdk::Window> window, CursorShape shape);
static void setCursorOfMainWindow (Glib::RefPtr<Gdk::Window> window, CursorShape shape);
};
diff --git a/rtgui/filmsimulation.cc b/rtgui/filmsimulation.cc
index f929048b8..c20f998f2 100644
--- a/rtgui/filmsimulation.cc
+++ b/rtgui/filmsimulation.cc
@@ -262,6 +262,12 @@ void ClutComboBox::setBatchMode(bool yes)
}
+void ClutComboBox::cleanup()
+{
+ cm.reset();
+ cm2.reset();
+}
+
void ClutComboBox::updateUnchangedEntry()
{
auto c = m_model()->children();
diff --git a/rtgui/filmsimulation.h b/rtgui/filmsimulation.h
index 5f66b579e..68bd6298d 100644
--- a/rtgui/filmsimulation.h
+++ b/rtgui/filmsimulation.h
@@ -18,6 +18,8 @@ public:
void setSelectedClut( Glib::ustring filename );
void setBatchMode(bool yes);
+ static void cleanup();
+
private:
void updateUnchangedEntry(); // in batchMode we need to add an extra entry "(Unchanged)". We do this whenever the widget is mapped (connecting to signal_map()), unless options.multiDisplayMode (see the comment below about cm2 in this case)
diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc
index f8129b0fb..9bb245a2a 100644
--- a/rtgui/guiutils.cc
+++ b/rtgui/guiutils.cc
@@ -560,6 +560,15 @@ void MyExpander::init()
closedPBuf = Gdk::Pixbuf::create_from_file(rtengine::findIconAbsolutePath("expander-closed-small.png"));
}
+void MyExpander::cleanup()
+{
+ inconsistentPBuf.reset();
+ enabledPBuf.reset();
+ disabledPBuf.reset();
+ openedPBuf.reset();
+ closedPBuf.reset();
+}
+
MyExpander::MyExpander(bool useEnabled, Gtk::Widget* titleWidget) :
enabled(false), inconsistent(false), flushEvent(false), expBox(nullptr),
child(nullptr), headerWidget(nullptr), statusImage(nullptr),
diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h
index 074e3bacc..17e8d677f 100644
--- a/rtgui/guiutils.h
+++ b/rtgui/guiutils.h
@@ -228,6 +228,7 @@ public:
/// Initialize the class by loading the images
static void init();
+ static void cleanup();
Glib::SignalProxy1< bool, GdkEventButton* > signal_button_release_event()
{
diff --git a/rtgui/main.cc b/rtgui/main.cc
index 59ceddecc..97cfcb997 100644
--- a/rtgui/main.cc
+++ b/rtgui/main.cc
@@ -239,6 +239,10 @@ void cleanup_rt()
{
rtengine::cleanup();
RTImage::cleanup();
+ MyExpander::cleanup();
+ ClutComboBox::cleanup();
+ mainWindowCursorManager.cleanup();
+ editWindowCursorManager.cleanup();
}
Indentation is broken, but hey: This was prepared under a "foreign" OS. :wink:
HTH, Flössie
Progress! It now crashes, as you'd probably expect, here - see frame #12
below, where it is trying to destroy the image from the file browser (which you have not attacked yet, per your comments).
#2 0x0000000803321099 in abort () at /usr/src/lib/libc/stdlib/abort.c:67
#3 0x000000080257a30f in () at /usr/local/lib/libglibmm-2.4.so.1
#4 0x00000008025cd84b in Glib::ObjectBase::~ObjectBase() (this=0x811d012d0, vtt=0x8026e96e8 <VTT for Gdk::Pixbuf+72>)
at objectbase.cc:160
#5 0x00000008026ca618 in Gdk::Pixbuf::~Pixbuf() (this=0x811d012c0) at pixbuf.cc:376
#6 0x00000008026ca689 in Gdk::Pixbuf::~Pixbuf() (this=0x811d012c0) at pixbuf.cc:376
#7 0x00000008025cd9e3 in Glib::ObjectBase::destroy_notify_() (this=0x811d012d0) at objectbase.cc:306
#8 0x00000008025cd94c in Glib::ObjectBase::destroy_notify_callback_(void*) (data=0x811d012d0) at objectbase.cc:283
#9 0x000000080205d093 in g_datalist_clear () at /usr/local/lib/libglib-2.0.so.0
#10 0x0000000801f8f584 in g_object_unref () at /usr/local/lib/libgobject-2.0.so.0
#11 0x00000008025cd8e9 in Glib::ObjectBase::unreference() const (this=0x811d012d0) at objectbase.cc:199
#12 0x0000000000528d4f in Glib::RefPtr<Gdk::Pixbuf>::~RefPtr() (this=0x12643a8 <FileBrowserEntry::ps>)
at /usr/local/include/glibmm-2.4/glibmm/refptr.h:273
#13 0x0000000803391081 in __cxa_finalize (dso=0x0) at /usr/src/lib/libc/stdlib/atexit.c:237
#14 0x0000000803320ce1 in exit (status=0) at /usr/src/lib/libc/stdlib/exit.c:74
(Still wondering whether it's something specific about mutexes on FreeBSD, about destruction order, or what else.)
@mandree AFAIK it's about destruction order. Search the net for freebsd atext dlopen
. I'll tackle the remaining problems next week. Not sure about the best solution yet, but it's good to identify the problematic places in advance.
Best, Flössie
@mandree (@Floessie) Does it crash the same with the hidpi-icons
branch (unpatched) ?
@Floessie I'll let you the final word on this, but my two cents is, considering the hidpi-branch that is in testing phase, to maybe use the RTImage where possible (which can handle a Gdk:Pixbuf and Cairo:ImageSurface), and update the RTImage dtor to delete the Pixbuf first.
For cases where using RTImage is not suitable, your solution is fine, or create a MyPixbuf utility class ?
@Hombre57 Let's wait for @mandree's tests with the hidpi-icons
branch. I am wondering if there really is a need for static Glib::RefPtr
s given the fact that they live until the very end when the OS kicks in to clean up the rest. Why not turn them into plain static pointers? Or will this give us leak alerts with ASAN and friends (I guess so)?
The hidpi-icons branch crashes here, as of 0407dc3487
#0 0x000000080344341a in thr_kill () at thr_kill.S:3
#1 0x0000000803441804 in __raise (s=6) at /usr/src/lib/libc/gen/raise.c:52
#2 0x00000008033b4099 in abort () at /usr/src/lib/libc/stdlib/abort.c:67
#3 0x00000008025cf30f in () at /usr/local/lib/libglibmm-2.4.so.1
#4 0x000000080262284b in Glib::ObjectBase::~ObjectBase() (this=0x80b86c950, vtt=0x802f39418 <VTT for Gtk::TreeStore+232>)
at objectbase.cc:160
#5 0x0000000802df9feb in Gtk::TreeStore::~TreeStore() (this=0x80b86c920) at treestore.cc:259
#6 0x0000000802dfa0e9 in Gtk::TreeStore::~TreeStore() (this=0x80b86c920) at treestore.cc:259
#7 0x00000008026229e3 in Glib::ObjectBase::destroy_notify_() (this=0x80b86c950) at objectbase.cc:306
#8 0x000000080262294c in Glib::ObjectBase::destroy_notify_callback_(void*) (data=0x80b86c950) at objectbase.cc:283
#9 0x00000008020bf093 in g_datalist_clear () at /usr/local/lib/libglib-2.0.so.0
#10 0x0000000801ff1584 in g_object_unref () at /usr/local/lib/libgobject-2.0.so.0
#11 0x00000008026228e9 in Glib::ObjectBase::unreference() const (this=0x80b86c950) at objectbase.cc:199
#12 0x00000000006867cf in Glib::RefPtr<Gtk::TreeStore>::~RefPtr() (this=0x80b94be50)
at /usr/local/include/glibmm-2.4/glibmm/refptr.h:273
#13 0x00000000007b7f6c in ClutComboBox::ClutModel::~ClutModel() (this=0x80b94be50) at ../rtgui/filmsimulation.h:32
#14 0x00000000007b45c8 in std::__1::default_delete<ClutComboBox::ClutModel>::operator()(ClutComboBox::ClutModel*) const
(this=0x12b84e0 <ClutComboBox::cm>, __ptr=0x80b94be50) at /usr/include/c++/v1/memory:2285
#15 0x00000000007b45c8 in std::__1::unique_ptr<ClutComboBox::ClutModel, std::__1::default_delete<ClutComboBox::ClutModel> >::reset(ClutComboBox::ClutModel*) (this=0x12b84e0 <ClutComboBox::cm>, __p=0x0) at /usr/include/c++/v1/memory:2598
#16 0x00000000007b45c8 in std::__1::unique_ptr<ClutComboBox::ClutModel, std::__1::default_delete<ClutComboBox::ClutModel> >::~unique_ptr() (this=0x12b84e0 <ClutComboBox::cm>) at /usr/include/c++/v1/memory:2552
#17 0x0000000803424081 in __cxa_finalize (dso=0x0) at /usr/src/lib/libc/stdlib/atexit.c:237
#18 0x00000008033b3ce1 in exit (status=0) at /usr/src/lib/libc/stdlib/exit.c:74
#19 0x0000000000504122 in _start (ap=<optimized out>, cleanup=<optimized out>) at /usr/src/lib/csu/amd64/crt1.c:76
Full crash details, now with glib20 debugging, too:
#0 0x000000080350841a in thr_kill () at thr_kill.S:3
#1 0x0000000803506804 in __raise (s=6) at /usr/src/lib/libc/gen/raise.c:52
id = 101669
#2 0x0000000803479099 in abort () at /usr/src/lib/libc/stdlib/abort.c:67
act = <optimized out>
#3 0x00000008026a330f in () at /usr/local/lib/libglibmm-2.4.so.1
#4 0x00000008026f684b in Glib::ObjectBase::~ObjectBase() (this=0x80b92c950, vtt=0x802f39418 <VTT for Gtk::TreeStore+232>)
at objectbase.cc:160
lock = {__m_ = @0x802728210}
#5 0x0000000802df9feb in Gtk::TreeStore::~TreeStore() (this=0x80b92c920) at treestore.cc:259
#6 0x0000000802dfa0e9 in Gtk::TreeStore::~TreeStore() (this=0x80b92c920) at treestore.cc:259
#7 0x00000008026f69e3 in Glib::ObjectBase::destroy_notify_() (this=0x80b92c950) at objectbase.cc:306
#8 0x00000008026f694c in Glib::ObjectBase::destroy_notify_callback_(void*) (data=0x80b92c950) at objectbase.cc:283
cppObject = 0x80b92c950
#9 0x00000008021685f5 in g_datalist_clear (datalist=0x80ba30dc0) at gdataset.c:273
data = 0x80bfd8fc0
i = 0
#10 0x000000080208446e in g_object_finalize (object=0x80ba30db0 [gtkmm__GtkTreeStore]) at gobject.c:1062
#11 0x000000080207d440 in g_object_unref (_object=0x80ba30db0) at gobject.c:3340
weak_locations = 0x0
object = 0x80ba30db0 [gtkmm__GtkTreeStore]
old_ref = 1
#12 0x00000008026f68e9 in Glib::ObjectBase::unreference() const (this=0x80b92c950) at objectbase.cc:199
#13 0x00000000006867cf in Glib::RefPtr<Gtk::TreeStore>::~RefPtr() (this=0x80ba22f40)
at /usr/local/include/glibmm-2.4/glibmm/refptr.h:273
#14 0x00000000007b7f6c in ClutComboBox::ClutModel::~ClutModel() (this=0x80ba22f40) at ../rtgui/filmsimulation.h:32
#15 0x00000000007b45c8 in std::__1::default_delete<ClutComboBox::ClutModel>::operator()(ClutComboBox::ClutModel*) const
(this=0x12b84e0 <ClutComboBox::cm>, __ptr=0x80ba22f40) at /usr/include/c++/v1/memory:2285
__tmp = 0x80ba22f40
#16 0x00000000007b45c8 in std::__1::unique_ptr<ClutComboBox::ClutModel, std::__1::default_delete<ClutComboBox::ClutModel> >::reset(ClutComboBox::ClutModel*) (this=0x12b84e0 <ClutComboBox::cm>, __p=0x0) at /usr/include/c++/v1/memory:2598
__tmp = 0x80ba22f40
#17 0x00000000007b45c8 in std::__1::unique_ptr<ClutComboBox::ClutModel, std::__1::default_delete<ClutComboBox::ClutModel> >::~unique_ptr() (this=0x12b84e0 <ClutComboBox::cm>) at /usr/include/c++/v1/memory:2552
#18 0x00000008034e9081 in __cxa_finalize (dso=0x0) at /usr/src/lib/libc/stdlib/atexit.c:237
phdr_info =
{dlpi_addr = 140737488345424, dlpi_name = 0x8012a004d <_rtld_bind_start+45> "H\211D$`A[AZAYAX_^YZX\235H\215d$\020\303f\220H\215\005\241\242\001", dlpi_phdr = 0x806800980, dlpi_phnum = 8808, dlpi_adds = 4095, dlpi_subs = 185, dlpi_tls_modid = 0, dlpi_tls_data = 0x2}
has_phdr = 0
p = <optimized out>
fn =
{fn_type = 2, fn_ptr = {std_func = 0x7b4530 <std::__1::unique_ptr<ClutComboBox::ClutModel, std::__1::default_delete<ClutComboBox::ClutModel> >::~unique_ptr()>, cxa_func = 0x7b4530 <std::__1::unique_ptr<ClutComboBox::ClutModel, std::__1::default_delete<ClutComboBox::ClutModel> >::~unique_ptr()>}, fn_arg = 0x12b84e0 <ClutComboBox::cm>, fn_dso = <synthetic pointer>}
#19 0x0000000803478ce1 in exit (status=0) at /usr/src/lib/libc/stdlib/exit.c:74
#20 0x0000000000504122 in _start (ap=<optimized out>, cleanup=<optimized out>) at /usr/src/lib/csu/amd64/crt1.c:76
argc = <optimized out>
env = 0x7fffffffd9d0
argv = 0x7fffffffd9c0
@mandree Could you re-test hidpi-icons
again?
@Floessie it appears that 51f06dfa6 Explicitly destroy static Glib::RefPtr<>`s on exit (fixes #3636)
shuts down properly now, without SIGABRT, with initial quick testing (i. e. open file browser, open image and process, and quit from there, or return to file browser, and quit from there).
We should certainly test some more, also on other platforms; I've only given FreeBSD 12.0-RELEASE on amd64 a shot so far, not Fedora 29 or whatever else, and we haven't played with compilers and other settings yet.
There are a few harmless messages on start-up (I also have mutex debugging turned on, not shown here):
RTScalable::init / setDPInScale(scale:1, DPI:96.000)
"Default" font size(10) * scale(1) / fontScale(1.111)
CSS:
* { font-size: 10pt}
@mandree
it appears that 51f06df Explicitly destroy static Glib::RefPtr<>`s on exit (fixes #3636) shuts down properly now, without SIGABRT, with initial quick testing (i. e. open file browser, open image and process, and quit from there, or return to file browser, and quit from there).
:tada: Thanks for testing!
We should certainly test some more, also on other platforms
We take care of that during the -rc1 cycle (I usually test on Debian for amd64, i386 and powerpc with GCC and Clang). Others test for different platforms. The scope of this issue is FreeBSD.
Would you like to take the role of the BSD tester for RT? This means you would occasionally compile dev
from source and report problems back here (basically what you've already done in this issue). It would be even better if you could provide BSD specific patches. And there's also Rawpedia, which needs some input for compiling on BSDs...
Now let's wait for @Hombre57 to merge hidpi-icons
into dev
.
Closing.
@Floessie: testing and patches on FreeBSD is one thing that I might occasionally do (feel free to ping me on IRC, I am usually around as m-a), however I do not care much about writing build instructions, because that means double effort: For FreeBSD, we have port and package described here https://freshports.org/graphics/rawtherapee/ and its Makefile contains everything I know, and about pkgsrc or Net/Open/DragonflyBSDs and whatnot, I have no clue.
Getting the rig set for compiling nontrivial C++ ports with dependencies is enough of a mess.
I've backported the fix from 51f06dfa to the FreeBSD port as of 5.5_1, ports r496692 to be precise. This should propagate to FreeBSD pre-built packages over the next two weeks.
@mandree We are about to release 5.6. If there's anything else you need upstream let us know.
@mandree We are about to release 5.6. If there's anything else you need upstream let us know.
@Floessie - FreeBSD will semi-freeze its stable packages quarterly, so if 5.6 were to be released out until, say, Thursday morning, we might make the 2019Q2 2nd quarter branch for FreeBSD packages.
For FreeBSD, be sure that you also clear() out the pixbufCache if 5.6 will still be using it after the `hidpi-icons merge:
I don't recall this was needed on the hidpi-icons branch when I tested it, but I'd thought I'd still mention it.
Building the dev
branch as of b9a5680d1, I see these warnings:
../rtengine/pixelshift.cc:84:17: warning: loop not vectorized: failed explicitly specified loop vectorization [-Wpass-failed=loop-vectorize]
#pragma omp simd
^
../rtengine/pixelshift.cc:101:17: warning: loop not vectorized: failed explicitly specified loop vectorization [-Wpass-failed=loop-vectorize]
#pragma omp simd
^
In file included from ../rtengine/cplx_wavelet_dec.cc:21:
../rtengine/cplx_wavelet_dec.h:48:9: warning: private field 'numThreads' is not used [-Wunused-private-field]
int numThreads;
^
Also, rtgui/CMakeLists.txt
contains this code near line 237 which is GCC specific, whereas FreeBSD usually employs clang instead of GCC, and -latomic is GCC-specific. Hence, the FreeBSD port is currently erasing this part:
if(OPENMP_FOUND AND NOT APPLE)
set(EXTRA_LIB_RTGUI ${EXTRA_LIB_RTGUI} "atomic")
endif()
Ping @Hombre57
@Beep6581 @mandree I've added a RTImage::cleanup
static function in m-bugfix
branch. I can't say/fix the OpenMP and cmakelist bug, but maybe @heckflosse or @Floessie can ?
As for the CMake condition: We could use CMAKE_CXX_COMPILER_ID
(since 2.8.10) or CMAKE_COMPILER_IS_GNUCC
(since 2.8.2) instead of NOT APPLE
. Ideas welcome.
Ah, thanks. Will look at the m-bugfix branch.
The libatomic thingy is not a showstopper though - I can nuke those three lines in the pre-configure stage and move on. Just thought I'd mention it since not All The World Uses GCC™ any more. I don't currently know what the real cause for requiring -latomic is - this should be checked from features and compile-and-link tests, because there seems to be a lot of patching going on in the distros, and it may be related to OpenMP which appears to be in some state of flux, at least on FreeBSD.
@Hombre57 m-bugfix
works well on FreeBSD 12.
@mandree I saw you use GCC for i386 in the commit message. This is also crucial for non-SSE2 i386 builds.
Just thought I'd mention it since not All The World Uses GCC™ any more.
I'm doing Clang builds on Linux and haven't run into this issue.
I don't currently know what the real cause for requiring -latomic is
Supporting atomic loads/stores which are not covered by intrinsics. Say you have a 32b arch and the code does 8B loads/stores (simplified).
Right, but I don't fully oversee the repercussions on the various FreeBSD architectures and toolchains.
@Hombre57 @Beep6581 To my surprise m-bugfix
doesn't seem to be part of dev
(and release-5.6
), yet. Isn't it deemed that important?
Quick look, the issue was not tagged 5.6, and as far as I can tell the branch m-bugfix
was not tested by the OP.
Ping @mandree
@Floessie what do you suggest?
@Beep6581 Leave it for 5.7
Concerning the libatomic
thing: I've successfully built 5.6-rc1 on FreeBSD 12 with Clang 6.0.1 from scratch without problems. Does this problem still persist, @mandree?
@Beep6581 @Floessie The m-bugfix
is quite safe and I don't see any reason not to merge it to dev : it adds a cleanup function along like for other class, and even if it doesn't solve this issue, it won't harm. So I'd merge it for 5.6.
@Beep6581 @Floessie The m-bugfix
is quite safe and I don't see any reason not to merge it to dev : it adds a cleanup function like for other class, and even if it doesn't solve this issue, it won't harm. So I'd merge it for 5.6.
Sorry, I got distracted and wasn't keeping this on my personal leisure TODO-list, so missed it. Thanks for the ping, am testing 5.6-rc1 and m-bugfix today. On 5.6-rc1, FreeBSD 12.0-RELEASE-p3, amd64 (think x86_64), the OMP vectorization warnings persist, as does "/usr/bin/ld: error: unable to find library -latomic" the libatomic-missing-under-clang issue. Compiler is FreeBSD clang v6.0.1/x86_64-unknown-freebsd12.0.
So. m-bugfix works on FreeBSD 12.0-RELEASE-p3 amd64 if I avoid libatomic, this way:
diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt
index 831f100e7..fa5c8e3b4 100644
--- a/rtgui/CMakeLists.txt
+++ b/rtgui/CMakeLists.txt
@@ -234,7 +234,7 @@ else()
)
endif()
-if(OPENMP_FOUND AND NOT APPLE)
+if(OPENMP_FOUND AND NOT APPLE AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
set(EXTRA_LIB_RTGUI ${EXTRA_LIB_RTGUI} "atomic")
endif()
Same thing with 5.6-rc1, also needs the patch above; for reasons I do not fully understand it does not seem to require m-bugfix, or I haven't reproduced the situation that caused the crash when I figured we'd need that. At any rate, m-bugfix looks cleaner than what I proposed earlier.
I'd vote to merge m-bugfix into release-5.6 and/or dev.
I need to test the other architectures (such as i386)/compilers (such as gcc) later (separately) and will only test 5.6-rc1 then.
Since we need another RC due to the scaling issues, I'm +1 for merging m-bugfix
for 5.6.
@Floessie is the cmake change above ok with you?
When quitting normally from RawTherapee 5.0 release GTK3 on FreeBSD 10.3 (amd64), I get this and a core dump: