bugGNU Octave - Bugs: bug #61994, Crash on GUI exiting with...

 
 

bug #61994: Crash on GUI exiting with octave_base_value objects still open.

Submitter:  John Donoghue <lostbard>
Submitted:  Sat 05 Feb 2022 02:00:08 PM UTC
 
Category:  Interpreter Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Segfault, Bus Error, etc.
Status:  Fixed Assigned to:  None
Originator Name:  JohnD Open/Closed:  * Closed
Release:  * 7.0.90 Operating System:  * Any
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment (Rich Markup)
   

Comment Type & Canned Response:
       

 

( Jump to the original submission )

Sun 20 Feb 2022 02:11:00 PM UTC, comment #36: 

Thanks again! The buildbots seem to be ok again with that change reverted. And the original issue still seems to be fixed reliably  for me. ­čĹŹ

I agree that it might be a better place to make the changes you described in comment #35 on the default branch.

Using the patch from that comment on top of a current tip (hg id 753e48aa488c) works for me on Linux. I haven't tested on Windows yet.

Should changeset fc530ec01070 be reapplied on the default branch after this change is applied?
Should we move to a new bug report for further changes and close this one as fixed?

Markus M├╝tzel <mmuetzel>
Project Member
Sat 19 Feb 2022 06:16:37 PM UTC, comment #35: 

After writing comment #33, I tried some other things and was able to duplicate the crash in the buildbot build tree for the mxe-octave-native-all configuration and I was able to get a core file to examine with gdb and it looked like the crash was happening when deleting the static dynamic_library::dynlib_rep::s_instances object.  The attached diff removes that object entirely and avoids the crash for me.

It seems the intent of the s_instances static data member was to avoid reloading libraries if there were still references to functions from a previously loaded library of the same name?  In the past maybe reloading forced the library to be closed?  But I don't see that it would happen now.  I'm also wondering now whether we need any of the complication in the dynamic_library class of trying track what functions have been loaded from the file and whether the file is out of date, etc.  Maybe now it can just be a wrapper to provide a consistent interface to the underlying dlopen/LoadLibrary functions?

But since this change is getting to be fairly significant, I'm also fine with undoing my previous change for version 7 and making the more substantial changes on default where we can do more testing.  I backed out the previous change here:

http://hg.savannah.gnu.org/hgweb/octave/rev/db0335e1b6e0

(file #52892)

John W. Eaton <jwe>
Project Administrator
Sat 19 Feb 2022 05:28:52 PM UTC, comment #34: 

I cannot recreate that crash either. Neither when building the documentation nor when running that command in the build tree nor with `make JOBS=10 hg-octave-dist`. It doesn't seem to matter if I unset `DISPLAY` or not (i.e., using "qt" or "gnuplot" as the graphics toolkit).

Maybe, the best way forward to not delay Octave 7 longer than necessary is to revert that changeset like you suggested and check if that prevents those crashes from happening. (At least until we understand why this is happening.)

Markus M├╝tzel <mmuetzel>
Project Member
Sat 19 Feb 2022 03:51:32 PM UTC, comment #33: 

It definitely could be due to changeset http://hg.savannah.gnu.org/hgweb/octave/rev/fc530ec01070, however I'm unable to duplicate the problem with

DISPLAY= /bin/bash run-octave -disable-asan --norc --silent --no-history --path /home/jwe/src/octave/doc/interpreter --eval "genpropdoc ('figure');" > doc/interpreter/plot-figureproperties.texi-t

on the same buildbot system where the failure is happening for the buildbot build, or by running the command in the actual same directory where the buildbot failure occurs while logged in as the buildbot user and running without DISPLAY set.  I see the gnuplot warning but not the crash.

For now, I can undo the change.

The failure happens when generating the distribution tar file for the current sources and I see that it doesn't use 'xvfb' for that build step.  We could also change that, but then a problem like this would have been unnoticed.

While looking at this problem I also noticed the following message in the
http://buildbot.octave.org:8010/#/builders/33/builds/1266/steps/6/logs/stdio log file:

sh: 1: dvipng: not found
warning: latex_renderer: a run-time test failed and the 'latex' interpreter has been disabled.
warning: called from
    text at line 218 column 10
    plotimages at line 107 column 7

I can install dvipng on the build system to avoid the warning.  I wouldn't make it a high priority, but I'm also wondering whether there is some easy change we can make so that we don't miss things like this in the buildbot log files.

John W. Eaton <jwe>
Project Administrator
Sat 19 Feb 2022 11:17:30 AM UTC, comment #32: 

The MXE builders on your buildbot farm were failing in the last few build attempts.
They seem to be using the gnuplot graphics toolkit (maybe because they are headless - not sure if that is important for that crash). They seem to be crashing when they try to create the the documentation for the graphics properties. E.g.:
http://buildbot.octave.org:8010/#/builders/20/builds/1124/steps/7/logs/stdio

warning: using the gnuplot graphics toolkit is discouraged

The gnuplot graphics toolkit is not actively maintained and has a number
of limitations that are unlikely to be fixed.  Communication with gnuplot
uses a one-directional pipe and limited information is passed back to the
Octave interpreter so most changes made interactively in the plot window
will not be reflected in the graphics properties managed by Octave.  For
example, if the plot window is closed with a mouse click, Octave will not
be notified and will not update its internal list of open figure windows.
The qt toolkit is recommended instead.
corrupted size vs. prev_size while consolidating
fatal: caught signal Aborted -- stopping myself...
/bin/bash: line 1: 3367749 Aborted                 /bin/bash run-octave -disable-asan --norc --silent --no-history --path ../doc/interpreter --eval "genpropdoc ('figure');" > doc/interpreter/plot-figureproperties.texi-t
make[3]: *** [Makefile:31701: doc/interpreter/plot-figureproperties.texi] Error 134

Could that be related to the latest changes to `__init_gnuplot__.cc`?

Markus M├╝tzel <mmuetzel>
Project Member
Fri 18 Feb 2022 07:04:25 PM UTC, comment #31: 

I'm also open to better names for these classes.  I couldn't think of anything better yesterday, but I'm not sure that "octave_base_dld_value" or "auto_shlib" (and probably others) are the best we could choose.

John W. Eaton <jwe>
Project Administrator
Fri 18 Feb 2022 07:01:59 PM UTC, comment #30: 

Yes, any .oct file that introduces a new type should derive from octave_base_dld_value instead of just octave_base_value so that it will automatically track the values created by that dynamically loaded function and prevent the .oct file from being closed until all functions and values that it creates are deleted.

I will try to add some comments about the way this new code is supposed to work and when/how it should be used.

John W. Eaton <jwe>
Project Administrator
Fri 18 Feb 2022 06:49:42 PM UTC, comment #29: 

Thanks! Works for me with your changes.

Just to make sure: In case something similar happens with classes in user code (or Octave packages) that inherit from octave_base_value, they should inherit from octave_base_dld_value instead?
Should that be documented somewhere? Should `examples\code\make_int.cc` be adapted?

Markus M├╝tzel <mmuetzel>
Project Member
Fri 18 Feb 2022 04:01:03 AM UTC, comment #28: 

I pushed a series of changesets and merged with default.  Marking as ready for test again.

John W. Eaton <jwe>
Project Administrator
Thu 17 Feb 2022 06:42:47 PM UTC, comment #27: 

Thanks for testing.  I'm working on a series of changesets that will do the same thing in a slightly nicer way.  I should be able to push it later today.

John W. Eaton <jwe>
Project Administrator
Thu 17 Feb 2022 06:03:41 PM UTC, comment #26: 

Thanks!
While I could reproduce the crash on exit pretty reliably before, it no longer crashes with the steps from comment #0 after the changes from comment #25. (Tested 10 times.)

Markus M├╝tzel <mmuetzel>
Project Member
Thu 17 Feb 2022 04:01:08 PM UTC, comment #25: 

Please try the attached patch that attempts to implement option #2 from comment #24.

At first, I thought that if I could just store a reference to the containing dynamic library (audiodevinfo.oct) in the audioplayer and audiorecorder classes (octave_base_value objects that are created by functions defined in audiodevinfo.oct) that it would be sufficient.  But then it was still possible to close the dynamic library from inside the audioplayer or audiorecorder destructors that are defined inside the dynamic library.  Doing that is no good and can result in a crash.  To avoid that, instead of allowing the containing dynamic_library object to be deleted when the audioplayer or audiorecorder objects go out of scope, the dynamic_library object is added to a global list of dynamic_libraries that can be deleted later.  This action just transfers ownership of the reference to the dynamic_library to the global list.  Since the dynamic_library object is also reference counted, the library won't really be closed until all references are deleted.  The global list of to-be-deleted dynamic_library objects is periodically cleared by the interpreter.  But because the list is global, it is not cleared when the interpreter goes out of scope.  So it is now OK if the GUI thread is still running and deletes the audioplayer object after the interpreter is done because there is still a reference to the audiodevinfo.oct file in the global list of to-be-deleted dynamic_library objects.  Then, finally, the list is cleared and the dynamic_library objects are unloaded and deleted when the destructors for global objects are called.

This change also removes the calls to mlock in the audiodevinfo.oct functions.  So now it should be possible to unload that .oct file if and only if all functions that it defines and octave_value objects created by it have been cleared.

(file #52877)

John W. Eaton <jwe>
Project Administrator
Thu 17 Feb 2022 03:51:22 AM UTC, comment #24: 

By adding a delay in the workspace_model::set_workspace function I was able to observe the crash with both the old and new terminal widgets.  The issue is that if the interpreter::shutdown actions finish before the workspace model is cleared, then it is possible for shared libraries like audiodevinfo.oct to be closed before all symbols created by them are deleted.  The audiodevinfo.oct file defines the audioplayer class, so attempting to call the destructor for an object of that class after the shared library has been closed results in a crash.

My attempts to fix this haven't necessarily been the wrong thing to do, but they are not getting at the real problem here.

I see a few options:

  1. Wait for the GUI to close before the interpreter clears all symbols and unloads shared libraries.  This is somewhat difficult to do with the current terminal/interpreter design and would require some refactoring even with the experimental terminal.
  2. Ensure that shared libraries that define classes aren't unloaded before all instances of the classes that they define are deleted.  How?
  3. Avoid calling the dynamic_library destructor (see oct-shlib.h) during the shutdown procedure.  Note that mlock is not enough (we already do that for the DLD functions defined in audiodevinfo.oct).  We override mlock by forcing symbols to be cleared near the end of interpreter::shutdown and even if we skip that, destructors for the dynamic library objects will eventually be deleted when the destructors are called for the symbol and function tables.

I'm not sure what the best long-term option is, but I'm leaning toward the third option as the best thing to do in the short term for the release.
also caused the

John W. Eaton <jwe>
Project Administrator
Tue 15 Feb 2022 07:20:29 PM UTC, comment #23: 

I repeated the test with that diff a few times. While it crash pretty much every time on exit before, it does no longer with that pause.

Markus M├╝tzel <mmuetzel>
Project Member
Tue 15 Feb 2022 06:17:58 PM UTC, comment #22: 

Does the attached change eliminate the crash for you?  Or at least make it less likely?  I'm not saying this is a fix, but I'm wondering whether pausing execution of the interpreter thread to allow the GUI to finish processing events will help avoid the crash.

(file #52857)

John W. Eaton <jwe>
Project Administrator
Tue 15 Feb 2022 05:24:29 PM UTC, comment #21: 

I'm seeing the crash at exit pretty consistently. Most of the time octave exits with signal 11. I saw it exiting with signal 9 once.
I'm not sure if it is the same that John D is seeing (looks pretty similar to me).

Attached is the output of `thread apply all where` at that point.

How can I check if the m_rep points to the audioplayer object?
(It was the only object in the workspace viewer.)

(file #52856)

Markus M├╝tzel <mmuetzel>
Project Member
Tue 15 Feb 2022 04:15:45 PM UTC, comment #20: 

I know it is tedious to try to get stack traces in cases like this, but it would be more useful to have the output of "thread apply all where" to see which threads still exist and what they are doing at the point of the crash.  If we can get that info it would be great, but the output you have in comment #19 already seems to confirm what I was thinking.

At this point, it appears that the GUI thread is executing the function that was queued to clear the workspace model/viewer and the crash is happening when it deletes the octave_value objects stored there.  My assumption was that it wouldn't matter whether the last reference to an octave_value object was deleted in the interpreter or GUI thread.  Either that assumption is wrong or something else is happening to cause the "m_rep" pointer for this object to be invalid at the point when the destructor is called in the GUI thread.

It would also be useful to confirm that the "m_rep" here pointed to the audioplayer class object (I would assume so if that is the only thing that was displayed in the workspace viewer prior to the crash).  It would also be useful to know whether this kind of crash can happen with other types of class objects of if it is something unique to the audioplayer object.

John W. Eaton <jwe>
Project Administrator
Tue 15 Feb 2022 03:00:16 PM UTC, comment #19: 

AFter 6 or 7 attempts with debugger on:

Thread 1 "octave-gui" received signal SIGSEGV, Segmentation fault.
0x00007f4af7367c62 in octave_value::~octave_value (this=0x7f4aa09a4730, __in_chrg=<optimized out>) at ../libinterp/octave-value/ov.h:387
387           delete m_rep;

gdb) where
#0  0x00007f4af7367c62 in octave_value::~octave_value (this=0x7f4aa09a4730, __in_chrg=<optimized out>)
    at ../libinterp/octave-value/ov.h:387
#1  octave_value::~octave_value (this=0x7f4aa09a4730, __in_chrg=<optimized out>) at ../libinterp/octave-value/ov.h:380
#2  __gnu_cxx::new_allocator<octave_value>::destroy<octave_value> (__p=0x7f4aa09a4730, this=<optimized out>)
    at /usr/include/c++/11/ext/new_allocator.h:168
#3  std::allocator_traits<std::allocator<octave_value> >::destroy<octave_value> (__p=0x7f4aa09a4730, __a=...)
    at /usr/include/c++/11/bits/alloc_traits.h:535
#4  Array<octave_value, std::allocator<octave_value> >::ArrayRep::deallocate (this=0x7f4aa09be1c0, len=1, data=0x7f4aa09a4730)
    at ../liboctave/array/Array.h:206
#5  Array<octave_value, std::allocator<octave_value> >::ArrayRep::~ArrayRep (this=0x7f4aa09be1c0, __in_chrg=<optimized out>)
    at ../liboctave/array/Array.h:187
#6  Array<octave_value, std::allocator<octave_value> >::~Array (this=0x7f4aa0a3aec0, __in_chrg=<optimized out>)
    at ../liboctave/array/Array.h:356
#7  Cell::~Cell (this=0x7f4aa0a3aec0, __in_chrg=<optimized out>) at ../libinterp/corefcn/Cell.h:52
#8  std::_Destroy<Cell> (__pointer=0x7f4aa0a3aec0) at /usr/include/c++/11/bits/stl_construct.h:151
#9  std::_Destroy_aux<false>::__destroy<Cell*> (__last=<optimized out>, __first=0x7f4aa0a3aec0)
    at /usr/include/c++/11/bits/stl_construct.h:163
#10 std::_Destroy<Cell*> (__last=<optimized out>, __first=<optimized out>) at /usr/include/c++/11/bits/stl_construct.h:196
#11 std::_Destroy<Cell*, Cell> (__last=0x7f4aa0a3aef0, __first=<optimized out>) at /usr/include/c++/11/bits/alloc_traits.h:854
#12 std::vector<Cell, std::allocator<Cell> >::~vector (this=0x7f4aa09e0008, __in_chrg=<optimized out>)
    at /usr/include/c++/11/bits/stl_vector.h:680
#13 octave_map::~octave_map (this=0x7f4aa09e0000, __in_chrg=<optimized out>) at ../libinterp/corefcn/oct-map.h:276
#14 0x00007f4af65fc85f in octave_class::~octave_class (this=0x7f4aa09dfff0, __in_chrg=<optimized out>)
    at /usr/include/c++/11/ext/new_allocator.h:89
#15 octave_class::~octave_class (this=0x7f4aa09dfff0, __in_chrg=<optimized out>) at ../libinterp/octave-value/ov-class.h:80
#16 0x00007f4af73f38a9 in octave_value::~octave_value (this=0x29422f0, __in_chrg=<optimized out>)
    at ../libinterp/octave-value/ov.h:387
#17 octave_value::~octave_value (this=0x29422f0, __in_chrg=<optimized out>) at ../libinterp/octave-value/ov.h:380
#18 octave::symbol_info::~symbol_info (this=0x29422d0, __in_chrg=<optimized out>) at ../libinterp/corefcn/syminfo.h:55
#19 __gnu_cxx::new_allocator<std::_List_node<octave::symbol_info> >::destroy<octave::symbol_info> (__p=0x29422d0, this=0x2389e00)
    at /usr/include/c++/11/ext/new_allocator.h:168
#20 std::allocator_traits<std::allocator<std::_List_node<octave::symbol_info> > >::destroy<octave::symbol_info> (__p=0x29422d0,
    __a=...) at /usr/include/c++/11/bits/alloc_traits.h:535
#21 std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::_M_erase (__position=
  {m_name = "a", m_value = {m_rep = 0x7f4aa09dfff0}, m_is_complex = false, m_is_sparse = false, m_is_formal = false, m_is_global = false, m_is_persistent = false}, this=0x2389e00) at /usr/include/c++/11/bits/stl_list.h:1925
#22 std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::erase (__position=..., this=0x2389e00)
    at /usr/include/c++/11/bits/list.tcc:158
#23 std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::erase (__last=..., __first=
  {m_name = "a", m_value = {m_rep = 0x7f4aa09dfff0}, m_is_complex = false, m_is_sparse = false, m_is_formal = false, m_is_global = false, m_is_persistent = false}, this=<optimized out>) at /usr/include/c++/11/bits/stl_list.h:1462
#24 std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::_M_assign_dispatch<std::_List_const_iterator<octave::symbol_info> > (this=this@entry=0x2389e00, __first2=..., __first2@entry=
  {m_name = <error reading variable: Cannot create a lazy string with address 0x0, and a non-zero length.>, m_value = {m_rep = 0x1}, m_is_complex = false, m_is_sparse = 211, m_is_formal = 196, m_is_global = 65, m_is_persistent = 254}, __last2=..., __last2@entry=
  {m_name = <error reading variable: Cannot create a lazy string with address 0x0, and a non-zero length.>, m_value = {m_rep = 0x1}, m_is_complex = false, m_is_sparse = 211, m_is_formal = 196, m_is_global = 65, m_is_persistent = 254})
    at /usr/include/c++/11/bits/list.tcc:318
#25 0x00007f4af73f38f8 in std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::operator= (
    __x=empty std::__cxx11::list, this=<optimized out>) at /usr/include/c++/11/bits/stl_list.h:282
#26 std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::operator= (__x=empty std::__cxx11::list,
    this=<optimized out>) at /usr/include/c++/11/bits/list.tcc:267
#27 octave::base_list<octave::symbol_info>::operator= (bl=..., this=<optimized out>) at ../liboctave/util/base-list.h:100
#28 octave::symbol_info_list::operator= (this=<optimized out>) at ../libinterp/corefcn/syminfo.h:103
#29 octave::workspace_model::clear_data (this=0x2389de0) at ../libgui/src/workspace-model.cc:222
#30 0x00007f4af73f3a82 in octave::workspace_model::set_workspace (this=0x2389de0, top_level=<optimized out>, syminfo=...)
    at ../libgui/src/workspace-model.cc:183
#31 0x00007f4af464cf49 in QObject::event(QEvent*) () from /lib64/libQt5Core.so.5
#32 0x00007f4af50f7443 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /lib64/libQt5Widgets.so.5
#33 0x00007f4af73a5a04 in octave::octave_qapplication::notify (this=0x227f810, receiver=<optimized out>, ev=<optimized out>)
    at ../libgui/src/octave-qobject.cc:146
#34 0x00007f4af46227d8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /lib64/libQt5Core.so.5
#35 0x00007f4af4625d46 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () from /lib64/libQt5Core.so.5
#36 0x00007f4af4674117 in postEventSourceDispatch(_GSource*, int (*)(void*), void*) () from /lib64/libQt5Core.so.5
#37 0x00007f4aee7dd05f in g_main_context_dispatch () from /lib64/libglib-2.0.so.0
#38 0x00007f4aee8322a8 in g_main_context_iterate.constprop () from /lib64/libglib-2.0.so.0
#39 0x00007f4aee7da853 in g_main_context_iteration () from /lib64/libglib-2.0.so.0
#40 0x00007f4af4673bb8 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /lib64/libQt5Core.so.5
#41 0x00007f4af46211e2 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /lib64/libQt5Core.so.5
#42 0x00007f4af4629724 in QCoreApplication::exec() () from /lib64/libQt5Core.so.5
#43 0x00007f4af73a2daf in octave::base_qobject::exec (this=this@entry=0x7ffe41c4d830) at ../libgui/src/octave-qobject.cc:424
#44 0x00007f4af73b4a2a in octave::qt_application::execute (this=this@entry=0x7ffe41c4dac0) at ../libgui/src/qt-application.cc:73
#45 0x000000000040237f in main (argc=9, argv=0x7ffe41c4de48) at ../src/main-gui.cc:132
(gdb)

John Donoghue <lostbard>
Project Member
Tue 15 Feb 2022 02:47:59 PM UTC, comment #18: 

If it is only crashing sometimes, then that sounds like a race condition.  I would guess that maybe the GUI thread is sometimes executing the code that clears the workspace viewer/model after the interpreter::shutdown has finished.  We probably need a way for the interpreter to wait for an "finished" signal from the GUI before it continues the shutdown process.

John W. Eaton <jwe>
Project Administrator
Tue 15 Feb 2022 02:32:56 PM UTC, comment #17: 

I havent seen a crash in windows since the changes, however  have seen an occasional crash in linux.

Previous to changes, in linux, on existing after creating the audioplayer it would crash consistently. Now it only happens sometimes.

John Donoghue <lostbard>
Project Member
Mon 14 Feb 2022 08:59:23 PM UTC, comment #16: 

I still see those:

https://savannah.gnu.org/bugs/?60365

so I assumed they are related to pipewire.

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Mon 14 Feb 2022 05:14:59 PM UTC, comment #15: 

I didn't use the experimental terminal widget.

I still see the same crash on exit with hg id 496e5214c609 (from a fresh checkout).

Maybe that is something specific to my audio hardware? The audioplayer object is created without issues. But Octave crashes on exit.

Are there other steps to reproduce that don't depend on hardware?

Markus M├╝tzel <mmuetzel>
Project Member
Sun 13 Feb 2022 05:51:26 PM UTC, comment #14: 

Hmm, I don't see the crash when using the current terminal widget but I do see it with the experimental terminal widget, but only if started in "gui mode" (i.e., starting the desktop when Octave starts).  The following change fixes that problem for me:

http://hg.savannah.gnu.org/hgweb/octave/rev/d6ca77706ab3

If I start Octave with

./run-octave --experimental-terminal-widget

then execute the "desktop" function to start the GUI, then create an audioplayer object, then use the titlebar button to close the GUI window there is no crash and Octave is back at the command prompt with the audioplayer object in the workspace.  Executing the "quit" function at that point also works properly for me.

John W. Eaton <jwe>
Project Administrator
Sun 13 Feb 2022 10:15:50 AM UTC, comment #13: 

With hg id e022eab3ea1b, Octave closes without issues with a figure still open when clicking the "x" in the upper right edge of the main window.
However, when I run the GUI, execute the command from comment #0 and close the GUI with that "x", Octave exits with:

$ ./run-octave --gui
octave exited with signal 11

The gdb backtrace is:

(gdb) bt
#0  0x00007f3286484f62 in octave_value::~octave_value()
    (this=0x7f31dc722e00, __in_chrg=<optimized out>)
    at ../libinterp/octave-value/ov.h:387
#1  octave_value::~octave_value() (
    this=0x7f31dc722e00, __in_chrg=<optimized out>)
    at ../libinterp/octave-value/ov.h:380
#2  __gnu_cxx::new_allocator<octave_value>::destroy<octave_value>(octave_value*) (__p=0x7f31dc722e00, this=<optimized out>)
    at /usr/include/c++/11/ext/new_allocator.h:168
#3  std::allocator_traits<std::allocator<octave_value> >::destroy<octave_value>(std::allocator<octave_value>&, octave_value*)
    (__p=0x7f31dc722e00, __a=<optimized out>)
    at /usr/include/c++/11/bits/alloc_traits.h:531
#4  Array<octave_value, std::allocator<octave_value> >::ArrayRep::deallocate(octave_value*, unsigned long) (this=0x7f31dc6bbb60, len=1, data=0x7f31dc722e00)
    at ../liboctave/array/Array.h:206
#5  Array<octave_value, std::allocator<octave_value> >::ArrayRep::~ArrayRep()
    (this=0x7f31dc6bbb60, __in_chrg=<optimized out>)
    at ../liboctave/array/Array.h:187
#6  Array<octave_value, std::allocator<octave_value> >::~Array()
    (this=0x7f32040057b0, __in_chrg=<optimized out>)
    at ../liboctave/array/Array.h:356
#7  Cell::~Cell() (this=0x7f32040057b0, __in_chrg=<optimized out>)
--Type <RET> for more, q to quit, c to continue without paging--c
   rp/corefcn/Cell.h:52
#8  std::_Destroy<Cell>(Cell*) (__pointer=0x7f32040057b0) at /usr/include/c++/11/bits/stl_construct.h:140
#9  std::_Destroy_aux<false>::__destroy<Cell*>(Cell*, Cell*) (__last=<optimized out>, __first=0x7f32040057b0) at /usr/include/c++/11/bits/stl_construct.h:152
#10 std::_Destroy<Cell*>(Cell*, Cell*) (__last=<optimized out>, __first=<optimized out>) at /usr/include/c++/11/bits/stl_construct.h:185
#11 std::_Destroy<Cell*, Cell>(Cell*, Cell*, std::allocator<Cell>&) (__last=0x7f32040057e0, __first=<optimized out>) at /usr/include/c++/11/bits/alloc_traits.h:746
#12 std::vector<Cell, std::allocator<Cell> >::~vector() (this=0x7f3204006f18, __in_chrg=<optimized out>) at /usr/include/c++/11/bits/stl_vector.h:680
#13 octave_map::~octave_map() (this=0x7f3204006f10, __in_chrg=<optimized out>) at ../libinterp/corefcn/oct-map.h:276
#14 0x00007f32868f8f1f in octave_class::~octave_class() (this=0x7f3204006f00, __in_chrg=<optimized out>) at /usr/include/c++/11/ext/new_allocator.h:89
#15 octave_class::~octave_class() (this=0x7f3204006f00, __in_chrg=<optimized out>) at ../libinterp/octave-value/ov-class.h:80
#16 0x00007f3287745929 in octave_value::~octave_value() (this=0x5615328e2c60, __in_chrg=<optimized out>) at ../libinterp/octave-value/ov.h:387
#17 octave_value::~octave_value() (this=0x5615328e2c60, __in_chrg=<optimized out>) at ../libinterp/octave-value/ov.h:380
#18 octave::symbol_info::~symbol_info() (this=0x5615328e2c40, __in_chrg=<optimized out>) at ../libinterp/corefcn/syminfo.h:55
#19 __gnu_cxx::new_allocator<std::_List_node<octave::symbol_info> >::destroy<octave::symbol_info>(octave::symbol_info*) (__p=0x5615328e2c40, this=0x56152f69a750) at /usr/include/c++/11/ext/new_allocator.h:168
#20 std::allocator_traits<std::allocator<std::_List_node<octave::symbol_info> > >::destroy<octave::symbol_info>(std::allocator<std::_List_node<octave::symbol_info> >&, octave::symbol_info*) (__p=0x5615328e2c40, __a=...) at /usr/include/c++/11/bits/alloc_traits.h:531
#21 std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::_M_erase(std::_List_iterator<octave::symbol_info>) (__position={m_name = "a", m_value = {m_rep = 0x7f3204006f00}, m_is_complex = false, m_is_sparse = false, m_is_formal = false, m_is_global = false, m_is_persistent = false}, this=0x56152f69a750) at /usr/include/c++/11/bits/stl_list.h:1925
#22 std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::erase(std::_List_const_iterator<octave::symbol_info>) (__position=Python Exception <class 'gdb.error'>: value has been optimized out
, this=0x56152f69a750) at /usr/include/c++/11/bits/list.tcc:158
#23 std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::erase(std::_List_const_iterator<octave::symbol_info>, std::_List_const_iterator<octave::symbol_info>) (__last=Python Exception <class 'gdb.error'>: value has been optimized out
, __first={m_name = "a", m_value = {m_rep = 0x7f3204006f00}, m_is_complex = false, m_is_sparse = false, m_is_formal = false, m_is_global = false, m_is_persistent = false}, this=<optimized out>) at /usr/include/c++/11/bits/stl_list.h:1462
#24 std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::_M_assign_dispatch<std::_List_const_iterator<octave::symbol_info> >(std::_List_const_iterator<octave::symbol_info>, std::_List_const_iterator<octave::symbol_info>, std::__false_type) (this=this@entry=0x56152f69a750, __first2=Python Exception <class 'gdb.error'>: value has been optimized out
, __first2@entry={m_name = <error reading variable: Cannot create a lazy string with address 0x0, and a non-zero length.>, m_value = {m_rep = 0x7f31dc7ac5a0}, m_is_complex = 48, m_is_sparse = 167, m_is_formal = 105, m_is_global = 47, m_is_persistent = 21}, __last2=Python Exception <class 'gdb.error'>: value has been optimized out
, __last2@entry={m_name = <error reading variable: Cannot create a lazy string with address 0x0, and a non-zero length.>, m_value = {m_rep = 0x7f31dc7ac5a0}, m_is_complex = 48, m_is_sparse = 167, m_is_formal = 105, m_is_global = 47, m_is_persistent = 21}) at /usr/include/c++/11/bits/list.tcc:318
#25 0x00007f3287745988 in std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::operator=(std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> > const&) (__x=empty std::__cxx11::list, this=<optimized out>) at /usr/include/c++/11/bits/stl_list.h:282
#26 std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::operator=(std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> > const&) (__x=empty std::__cxx11::list, this=<optimized out>) at /usr/include/c++/11/bits/list.tcc:267
#27 octave::base_list<octave::symbol_info>::operator=(octave::base_list<octave::symbol_info> const&) (bl=..., this=<optimized out>) at ../liboctave/util/base-list.h:100
#28 octave::symbol_info_list::operator=(octave::symbol_info_list const&) (this=<optimized out>) at ../libinterp/corefcn/syminfo.h:103
#29 octave::workspace_model::clear_data() (this=0x56152f69a730) at ../libgui/src/workspace-model.cc:222
#30 0x00007f3287745b26 in octave::workspace_model::set_workspace(bool, bool, octave::symbol_info_list const&) (this=0x56152f69a730, top_level=<optimized out>, syminfo=...) at ../libgui/src/workspace-model.cc:183
#31 0x00007f328364f73e in QObject::event(QEvent*) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#32 0x00007f32841106b3 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#33 0x00007f32876f352b in octave::octave_qapplication::notify(QObject*, QEvent*) (this=0x56152f4705a0, receiver=<optimized out>, ev=<optimized out>) at ../libgui/src/octave-qobject.cc:146
#34 0x00007f328362216a in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#35 0x00007f3283625257 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#36 0x00007f328367bef7 in  () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#37 0x00007f3280d4c8bb in g_main_context_dispatch () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#38 0x00007f3280d9ff08 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#39 0x00007f3280d4a003 in g_main_context_iteration () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#40 0x00007f328367b548 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#41 0x00007f3283620a9b in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#42 0x00007f3283629024 in QCoreApplication::exec() () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#43 0x00007f32876f0343 in octave::base_qobject::exec() (this=this@entry=0x7fffc5581950) at ../libgui/src/octave-qobject.cc:424
#44 0x00007f3287703791 in octave::qt_application::execute() (this=this@entry=0x7fffc5581be0) at ../libgui/src/qt-application.cc:73
#45 0x000056152e0ab536 in main(int, char**) (argc=9, argv=0x7fffc5581f58) at ../src/main-gui.cc:132

Markus M├╝tzel <mmuetzel>
Project Member
Sat 12 Feb 2022 09:27:45 PM UTC, comment #12: 

I pushed one more change.  After this one, the workspace model should be cleared just before the event manager is disabled.  The idea is for the GUI to not be holding any references to interpreter objects after the interpreter exits.  There may still be some ways to screw things up and cause a crash on exit.  See the comments in the patch for some possible issues and solutions we might try in the future.

John W. Eaton <jwe>
Project Administrator
Sat 12 Feb 2022 07:30:47 PM UTC, comment #11: 

I pushed the following additional change and creating figures during the build process and things like

./run-octave --eval "sombrero; pause (1)"

appear to work for me.

http://hg.savannah.gnu.org/hgweb/octave/rev/dadbfe6fddd6

But I forgot to test the original case until after I pushed and now I'm again seeing crashes when exiting the GUI when classdef objects exist.  Whac-a-mole!

John W. Eaton <jwe>
Project Administrator
Sat 12 Feb 2022 06:00:39 PM UTC, comment #10: 

OK, you should also be able to duplicate the crash if you start Octave now (with or without the gui) then create a graphics object and then exit Octave while the graphics object still exists.

Shutdown is hard.  I recommend never closing Octave.

Seriously though, I'll take another look at this shutdown path.

John W. Eaton <jwe>
Project Administrator
Sat 12 Feb 2022 05:44:54 PM UTC, comment #9: 

Looks like this is causing segfaults when plotting for the buildbots. E.g.: http://buildbot.octave.org:8010/#/builders/34/builds/420/steps/6/logs/stdio

Markus M├╝tzel <mmuetzel>
Project Member
Sat 12 Feb 2022 05:38:30 PM UTC, comment #8: 

Verified changeset.  Marking as fixed and closing report.

Rik <rik5>
Project Administrator
Sat 12 Feb 2022 05:28:01 PM UTC, comment #7: 

It looks like the workspace model used by the workspace viewer is being deleted after the interpreter has already executed its shutdown procedure.  Since the workspace model is holding references to octave_value objects, that can cause trouble.  I pushed the following changeset so that the GUI does not attempt to shut down the interpreter.  This change appears to avoid the problem and works for me with both the current and experimental terminal widgets.

http://hg.savannah.gnu.org/hgweb/octave/rev/fb0d6b1e0b64

There may still be some issues with some unusual shutdown sequences.  For example, what happens if a classdef destructor or a graphics "closerequestfcn" tries to create some additional graphics objects as Octave is trying to exit?  Or attempts to restart the GUI (possible with desktop function when using the experimental terminal widget)?  I don't know that we have solutions for those problems yet.

I made the change that caused Octave to call interpreter::shutdown from interpreter_qobject::execute whether using the current or experimental terminal widget in this changeset:  http://hg.savannah.gnu.org/hgweb/octave/rev/f6ad83cbe3c4  Whatever my thoughts were then, I now think that was a mistake as it seems best for the GUI to be closed and then for the Octave interpreter to exit and not have the GUI try to shut down the interpreter.

John W. Eaton <jwe>
Project Administrator
Sat 12 Feb 2022 01:03:30 PM UTC, comment #6: 

.. well other packages sometimes? It was consistently doing it the other day, now only the audioplayer is a consistent crash.

John Donoghue <lostbard>
Project Member
Sat 12 Feb 2022 12:37:56 AM UTC, comment #5: 

I can cause the same issue with the instrument control package and audio package - it seems like anything that creates its own c++ octave class type

John Donoghue <lostbard>
Project Member
Thu 10 Feb 2022 08:21:07 PM UTC, comment #4: 

what does the Windows 'crash on shutdown' process look like? I just went through the comment #0 procedure with Windows 10 and Octave 6.4.0 and didn't notice anything odd about the program exit.

report supposedly depends on bug #57945, but that says a segfault should be the result.

Also, are audioplayer objects the only one we've recreated this with?

Nicholas Jankowski <nrjank>
Project Member
Thu 10 Feb 2022 06:52:57 PM UTC, comment #3: 

As a followup, I can also replicate in linux in octave-6.2.1 and octave-5.2.0

John Donoghue <lostbard>
Project Member
Thu 10 Feb 2022 03:57:46 PM UTC, comment #2: 

Unfortunately, I just can confirm this (2/10/22).

Rik <rik5>
Project Administrator
Sat 05 Feb 2022 05:58:58 PM UTC, comment #1: 

Thread 1 "octave-gui" received signal SIGSEGV, Segmentation fault.
0x00007f4fa43d1cb2 in octave_value::~octave_value (this=0x7f4f3c7c0520, __in_chrg=<optimized out>) at ../libinterp/octave-value/ov.h:387
387              delete m_rep;
(gdb) p m_rep
$1 = (octave_base_value *) 0x7f4f3c7b3760
(gdb) p m_rep->count
$2 = {m_count = {<std::__atomic_base<long>> = {static _S_alignment = 8, _M_i = 0}, static is_always_lock_free = true}}
(gdb)

Call stack

(gdb) where
#0  0x00007f4fa43d1cb2 in octave_value::~octave_value() (this=0x7f4f3c7c0520, __in_chrg=<optimized out>)
    at ../libinterp/octave-value/ov.h:387
#1  octave_value::~octave_value() (this=0x7f4f3c7c0520, __in_chrg=<optimized out>) at ../libinterp/octave-value/ov.h:380
#2  __gnu_cxx::new_allocator<octave_value>::destroy<octave_value>(octave_value*) (__p=0x7f4f3c7c0520, this=<optimized out>)
    at /usr/include/c++/11/ext/new_allocator.h:168
#3  std::allocator_traits<std::allocator<octave_value> >::destroy<octave_value>(std::allocator<octave_value>&, octave_value*)
    (__p=0x7f4f3c7c0520, __a=<optimized out>) at /usr/include/c++/11/bits/alloc_traits.h:535
#4  Array<octave_value, std::allocator<octave_value> >::ArrayRep::deallocate(octave_value*, unsigned long)
    (this=0x7f4f3c7c53b0, len=1, data=0x7f4f3c7c0520) at ../liboctave/array/Array.h:206
#5  Array<octave_value, std::allocator<octave_value> >::ArrayRep::~ArrayRep() (this=0x7f4f3c7c53b0, __in_chrg=<optimized out>)
    at ../liboctave/array/Array.h:187
#6  Array<octave_value, std::allocator<octave_value> >::~Array() (this=0x7f4f3ca1d630, __in_chrg=<optimized out>)
    at ../liboctave/array/Array.h:356
#7  Cell::~Cell() (this=0x7f4f3ca1d630, __in_chrg=<optimized out>) at ../libinterp/corefcn/Cell.h:52
#8  std::_Destroy<Cell>(Cell*) (__pointer=0x7f4f3ca1d630) at /usr/include/c++/11/bits/stl_construct.h:151
#9  std::_Destroy_aux<false>::__destroy<Cell*>(Cell*, Cell*) (__last=<optimized out>, __first=0x7f4f3ca1d630)
    at /usr/include/c++/11/bits/stl_construct.h:163
#10 std::_Destroy<Cell*>(Cell*, Cell*) (__last=<optimized out>, __first=<optimized out>)
    at /usr/include/c++/11/bits/stl_construct.h:196
#11 std::_Destroy<Cell*, Cell>(Cell*, Cell*, std::allocator<Cell>&) (__last=0x7f4f3ca1d660, __first=<optimized out>)
    at /usr/include/c++/11/bits/alloc_traits.h:750
#12 std::vector<Cell, std::allocator<Cell> >::~vector() (this=0x7f4f3ca01d18, __in_chrg=<optimized out>)
    at /usr/include/c++/11/bits/stl_vector.h:680
#13 octave_map::~octave_map() (this=0x7f4f3ca01d10, __in_chrg=<optimized out>) at ../libinterp/corefcn/oct-map.h:276
#14 0x00007f4fa366658f in octave_class::~octave_class() (this=0x7f4f3ca01d00, __in_chrg=<optimized out>)
    at /usr/include/c++/11/ext/new_allocator.h:89
#15 octave_class::~octave_class() (this=0x7f4f3ca01d00, __in_chrg=<optimized out>) at ../libinterp/octave-value/ov-class.h:80
#16 0x00007f4fa4404f40 in octave_value::~octave_value() (this=0x7f4f800177f0, __in_chrg=<optimized out>)
    at ../libinterp/octave-value/ov.h:387
#17 octave_value::~octave_value() (this=0x7f4f800177f0, __in_chrg=<optimized out>) at ../libinterp/octave-value/ov.h:380
#18 octave::symbol_info::~symbol_info() (this=0x7f4f800177d0, __in_chrg=<optimized out>) at ../libinterp/corefcn/syminfo.h:55
#19 __gnu_cxx::new_allocator<std::_List_node<octave::symbol_info> >::destroy<octave::symbol_info>(octave::symbol_info*)
    (__p=0x7f4f800177d0, this=0x25d9a70) at /usr/include/c++/11/ext/new_allocator.h:168
#20 std::allocator_traits<std::allocator<std::_List_node<octave::symbol_info> > >::destroy<octave::symbol_info>(std::allocator<std::_List_node<octave::symbol_info> >&, octave::symbol_info*) (__p=0x7f4f800177d0, __a=...)
    at /usr/include/c++/11/bits/alloc_traits.h:535
#21 std::__cxx11::_List_base<octave::symbol_info, std::allocator<octave::symbol_info> >::_M_clear() (this=0x25d9a70)
    at /usr/include/c++/11/bits/list.tcc:77
#22 0x00007f4fa4411461 in std::__cxx11::_List_base<octave::symbol_info, std::allocator<octave::symbol_info> >::~_List_base()
    (this=0x25d9a70, __in_chrg=<optimized out>) at /usr/include/c++/11/bits/stl_list.h:498
#23 std::__cxx11::list<octave::symbol_info, std::allocator<octave::symbol_info> >::~list()
    (this=0x25d9a70, __in_chrg=<optimized out>) at /usr/include/c++/11/bits/stl_list.h:827
#24 octave::base_list<octave::symbol_info>::~base_list() (this=0x25d9a68, __in_chrg=<optimized out>)
    at ../liboctave/util/base-list.h:102
#25 octave::symbol_info_list::~symbol_info_list() (this=0x25d9a68, __in_chrg=<optimized out>)
    at ../libinterp/corefcn/syminfo.h:105
#26 octave::workspace_model::~workspace_model() (this=0x25d9a50, __in_chrg=<optimized out>) at ../libgui/src/workspace-model.h:54
#27 octave::workspace_model::~workspace_model() (this=0x25d9a50, __in_chrg=<optimized out>) at ../libgui/src/workspace-model.h:54
#28 octave::base_qobject::~base_qobject() (this=this@entry=0x7ffdd07a06d0, __in_chrg=<optimized out>)
    at ../libgui/src/octave-qobject.cc:392
#29 0x00007f4fa441ea75 in octave::qt_application::execute() (this=this@entry=0x7ffdd07a0960) at ../libgui/src/qt-application.cc:74
#30 0x000000000040237f in main(int, char**) (argc=2, argv=0x7ffdd07a0ce8) at ../src/main-gui.cc:132
(gdb)

John Donoghue <lostbard>
Project Member
Sat 05 Feb 2022 02:00:08 PM UTC, original submission:  

Its been reported before but the last bug was 'fixed' as it appeared to have stopped happending. (Bug #57945)

Run octave in gui mode: octave --gui

Create a audio player object

a = audioplayer([1:100], 44000)

Close octave by clicking on the close gadget on the octave title bar.

Octave closes, but crashes during the shutdown.

A quick run with debug - stops for me at:

Thread 1 "octave-gui" received signal SIGSEGV, Segmentation fault.
0x00007ff5bb278c22 in octave_value::~octave_value (this=0x7ff5549832d0, __in_chrg=<optimized out>) at ../libinterp/octave-value/ov.h:387


I can make it happen in both linux and windows using same method.

I can cause the same error with external octave packages as well by creating an object and not clearing it before closing by the close button.

John Donoghue <lostbard>
Project Member

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #52857:  diffs.txt added by jwe (477B - text/plain)
file #52856:  audioplayer-exit.txt added by mmuetzel (26KiB - text/plain)

 

Carbon-Copy List
  • -email is unavailable- added by dasergatskov (Posted a comment)
  • -email is unavailable- added by mmuetzel (Posted a comment)
  • -email is unavailable- added by jwe (Posted a comment)
  • -email is unavailable- added by nrjank (Posted a comment)
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by lostbard (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only project members can vote.

     

     

     

     

    Follow 16 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2022-02-27 rik5 Dependencies- bugs #55254 is dependent
    2022-02-20 mmuetzel StatusReady For Test Fixed
        Open/ClosedOpen Closed
    2022-02-19 jwe Attached File- Added dynamic-library-instances-diffs.txt, #52892
    2022-02-18 jwe StatusIn Progress Ready For Test
    2022-02-17 jwe Attached File- Added dynlib-delete-later-diffs.txt, #52877
    2022-02-15 jwe Attached File- Added diffs.txt, #52857
    2022-02-15 mmuetzel Attached File- Added audioplayer-exit.txt, #52856
    2022-02-12 mmuetzel StatusFixed In Progress
        Open/ClosedClosed Open
    2022-02-12 rik5 StatusReady For Test Fixed
        Open/ClosedOpen Closed
    2022-02-12 jwe StatusConfirmed Ready For Test
    2022-02-10 rik5 StatusNone Confirmed
    2022-02-05 lostbard Operating SystemMicrosoft Windows Any
    2022-02-05 lostbard Dependencies- Depends on bugs #57945

    Back to the top


    Powered by Savane 3.9