Segfault crash associated with Chronoblob2

A user found this bug and reported it in this thread: Alright Devices Chronoblob2: Please verify this bug and tell me where to report it

I’m using Ubuntu 19.04, Rack 1.1.3, and Alright Devices plugin 1.0.0. I’ve found that I can reproduce the crash by doing the following:

  • Construct a patch consisting only of two instances of Chronoblob2 (not even an audio interface) and no patch cables
  • Delete one of the instances and then attempt to Save As
  • Undo, delete the same instance again, and Save As

This happens both with the binary release and with a freshly built from source version running in a gdb session.

I’m no expert on desktop software development but as far as I can tell it’s not actually crashing from my plugin’s code. Rather, it looks like the crash is deeply nested within a call to rack::Window::run(). However, it is definitely associated with the presence of two Chronoblob2 instances. I tried the same thing with two instances of T-Wrex, and two instances of some Fundamental module but could not make it crash.

Here’s my gdb backtrace:

#0  0x00007ffff72061ed in __GI___libc_free (mem=0x16) at malloc.c:3109
#1  0x00007fffd80c3ac9 in  () at /lib/x86_64-linux-gnu/
#2  0x00007fffd80c4588 in  () at /lib/x86_64-linux-gnu/
#3  0x00007fffd80c4516 in  () at /lib/x86_64-linux-gnu/
#4  0x00007fffd80c4490 in  () at /lib/x86_64-linux-gnu/
#5  0x00007fffd80c4516 in  () at /lib/x86_64-linux-gnu/
#6  0x00007fffd80c4516 in  () at /lib/x86_64-linux-gnu/
#7  0x00007fffd80c4516 in  () at /lib/x86_64-linux-gnu/
#8  0x00007fffd80c4516 in  () at /lib/x86_64-linux-gnu/
#9  0x00007fffd80c4490 in  () at /lib/x86_64-linux-gnu/
#10 0x00007fffd80c4490 in  () at /lib/x86_64-linux-gnu/
#11 0x00007fffd80a28d5 in  () at /lib/x86_64-linux-gnu/
#12 0x00007fffd8093f87 in  () at /lib/x86_64-linux-gnu/
#13 0x00007ffff77ddf93 in g_object_unref () at /lib/x86_64-linux-gnu/
#14 0x00007fffe8120408 in  () at /usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/
#15 0x00007ffff6c119a3 in gdk_pixbuf_loader_close () at /lib/x86_64-linux-gnu/
#16 0x00007ffff6c0e32b in  () at /lib/x86_64-linux-gnu/
#17 0x00007ffff6c0f24d in gdk_pixbuf_new_from_stream_at_scale () at /lib/x86_64-linux-gnu/
#18 0x00007ffff7923a09 in  () at /lib/x86_64-linux-gnu/
#19 0x00007ffff7926b2a in gtk_icon_info_load_icon () at /lib/x86_64-linux-gnu/
#20 0x00007ffff7926ca6 in gtk_icon_theme_load_icon () at /lib/x86_64-linux-gnu/
#21 0x00007ffff7900e77 in  () at /lib/x86_64-linux-gnu/
#22 0x00007ffff79011d8 in  () at /lib/x86_64-linux-gnu/
#23 0x00007ffff7902a0c in  () at /lib/x86_64-linux-gnu/
#24 0x00007ffff77d8e8d in g_closure_invoke () at /lib/x86_64-linux-gnu/
#25 0x00007ffff77ebdad in  () at /lib/x86_64-linux-gnu/
#26 0x00007ffff77f54ae in g_signal_emit_valist () at /lib/x86_64-linux-gnu/
#27 0x00007ffff77f5b6f in g_signal_emit () at /lib/x86_64-linux-gnu/
#28 0x00007ffff7a6b89c in  () at /lib/x86_64-linux-gnu/
#29 0x00007ffff78a52c5 in  () at /lib/x86_64-linux-gnu/
#30 0x00007ffff7a6b8cf in  () at /lib/x86_64-linux-gnu/
#31 0x00007ffff7a6e2a3 in  () at /lib/x86_64-linux-gnu/
#32 0x00007ffff7a7349a in gtk_widget_set_parent () at /lib/x86_64-linux-gnu/
#33 0x00007ffff78a5ee4 in  () at /lib/x86_64-linux-gnu/
#34 0x00007ffff7907fbe in  () at /lib/x86_64-linux-gnu/
#35 0x00007ffff77de562 in  () at /lib/x86_64-linux-gnu/
#36 0x00007ffff77e05c4 in g_object_new_valist () at /lib/x86_64-linux-gnu/
#37 0x00007ffff77e08f9 in g_object_new () at /lib/x86_64-linux-gnu/
#38 0x00007ffff79083bd in  () at /lib/x86_64-linux-gnu/
#39 0x00007ffff79084ca in gtk_file_chooser_dialog_new () at /lib/x86_64-linux-gnu/
#40 0x000055555579641c in osdialog_file
    (action=action@entry=OSDIALOG_SAVE, path=0x7fffffffd730 "./patches", filename=0x7fffffffd750 "", filters=filters@entry=0x5555566e7000) at dep/osdialog/osdialog_gtk2.c:71
#41 0x000055555571df17 in rack::PatchManager::saveAsDialog() (this=0x5555563aa7e0) at /usr/include/c++/8/bits/basic_string.h:2290
#42 0x000055555576ebc3 in rack::app::Scene::onHoverKey(rack::event::HoverKey const&) (this=0x5555563ce7f0, e=...)
    at src/app/Scene.cpp:93
#43 0x0000555555746536 in rack::event::State::handleKey(rack::math::Vec, int, int, int, int)
    (this=<optimized out>, pos=..., key=<optimized out>, 
    key@entry=83, scancode=scancode@entry=39, action=action@entry=1, mods=mods@entry=35) at /usr/include/c++/8/bits/stl_iterator.h:133
#44 0x000055555574077b in rack::keyCallback(GLFWwindow*, int, int, int, int)
    (win=<optimized out>, key=83, scancode=39, action=1, mods=35) at src/window.cpp:172
#45 0x00005555557a67e5 in processEvent (event=0x7fffffffd9f0) at /tyler/repos/Rack/dep/glfw/src/x11_window.c:1264
#46 0x00005555557a67e5 in _glfwPlatformPollEvents () at /tyler/repos/Rack/dep/glfw/src/x11_window.c:2698
#47 0x000055555579e9ff in glfwPollEvents () at /tyler/repos/Rack/dep/glfw/src/window.c:1070
#48 0x00005555557409b2 in rack::Window::run() (this=0x555555c70600) at src/window.cpp:327
#49 0x00005555556bd8cc in main(int, char**) (argc=<optimized out>, argv=<optimized out>) at src/main.cpp:186

And my log.txt with the stack trace at the end:

[0.000 info src/main.cpp:113] VCV Rack v1.1.3
[0.000 info src/main.cpp:114] Linux 5.0.0-20-generic #21-Ubuntu SMP Mon Jun 24 09:32:09 UTC 2019 x86_64
[0.000 info src/main.cpp:120] Args: ./Rack 
[0.000 info src/main.cpp:123] System directory: .
[0.000 info src/main.cpp:124] User directory: /home/tyler/.Rack
[0.000 info src/settings.cpp:213] Loading settings /home/tyler/.Rack/settings-v1.json
[0.000 info src/main.cpp:146] Initializing environment
[0.034 info src/plugin.cpp:157] Loaded plugin Core v1.1.3 from 
[0.035 info src/plugin.cpp:157] Loaded plugin AlrightDevices v1.0.0 from /home/tyler/.Rack/plugins-v1/AlrightDevices
[0.037 info src/plugin.cpp:157] Loaded plugin AudibleInstruments v1.0.0 from /home/tyler/.Rack/plugins-v1/AudibleInstruments
[0.038 info src/plugin.cpp:157] Loaded plugin Befaco v1.0.0 from /home/tyler/.Rack/plugins-v1/Befaco
[0.038 info src/plugin.cpp:157] Loaded plugin ESeries v1.0.0 from /home/tyler/.Rack/plugins-v1/ESeries
[0.040 info src/plugin.cpp:157] Loaded plugin Fundamental v1.0.1 from /home/tyler/.Rack/plugins-v1/Fundamental
[0.048 info src/main.cpp:161] Initializing app
[0.134 info src/bridge.cpp:382] Bridge server started
[0.173 info src/window.cpp:227] Window content scale: 1.000000
[0.245 info src/window.cpp:267] Renderer: AMD PITCAIRN (DRM 2.50.0, 5.0.0-20-generic, LLVM 8.0.0)
[0.245 info src/window.cpp:268] OpenGL: 4.5 (Compatibility Profile) Mesa 19.0.2
[0.246 info src/window.cpp:33] Loaded font ./res/fonts/DejaVuSans.ttf
[0.247 info src/window.cpp:72] Loaded SVG ./res/ComponentLibrary/RackBusboard.svg
[0.247 info src/settings.cpp:196] Saving settings /home/tyler/.Rack/settings-v1.json
[0.699 warn src/plugin.cpp:424] VCV account has plugin Grayscale but no manifest was found
[1.372 info src/patch.cpp:161] Loading patch /home/tyler/.Rack/autosave-v1.vcv
[1.383 info src/window.cpp:72] Loaded SVG /home/tyler/.Rack/plugins-v1/AlrightDevices/res/chronoblob2.svg
[1.383 info src/window.cpp:72] Loaded SVG ./res/ComponentLibrary/ScrewSilver.svg
[1.383 info src/window.cpp:72] Loaded SVG ./res/ComponentLibrary/Rogan1PSWhite.svg
[1.383 info src/window.cpp:72] Loaded SVG ./res/ComponentLibrary/Rogan3PSWhite.svg
[1.384 info src/window.cpp:72] Loaded SVG ./res/ComponentLibrary/Trimpot.svg
[1.384 info src/window.cpp:72] Loaded SVG ./res/ComponentLibrary/PJ301M.svg
[1.384 info src/window.cpp:72] Loaded SVG /home/tyler/.Rack/plugins-v1/AlrightDevices/res/PB6149L-off.svg
[1.384 info src/window.cpp:72] Loaded SVG /home/tyler/.Rack/plugins-v1/AlrightDevices/res/SSSF012100-left.svg
[1.384 info src/window.cpp:72] Loaded SVG /home/tyler/.Rack/plugins-v1/AlrightDevices/res/SSSF012100-right.svg
[1.384 info src/window.cpp:72] Loaded SVG ./res/ComponentLibrary/TL1105_0.svg
[1.384 info src/window.cpp:72] Loaded SVG ./res/ComponentLibrary/TL1105_1.svg
[1.385 info src/main.cpp:173] Starting engine
[1.385 info src/main.cpp:185] Running window
[5.554 fatal src/main.cpp:38] Fatal signal 11. Stack trace:
47: ./Rack() [0x56d951]
46: /lib/x86_64-linux-gnu/ [0x7f6f46033f60]
45: /lib/x86_64-linux-gnu/ [0x7f6f460891ed]
44: /lib/x86_64-linux-gnu/ [0x7f6eed599ac9]
43: /lib/x86_64-linux-gnu/ [0x7f6eed59a588]
42: /lib/x86_64-linux-gnu/ [0x7f6eed59a516]
41: /lib/x86_64-linux-gnu/ [0x7f6eed59a516]
40: /lib/x86_64-linux-gnu/ [0x7f6eed59a516]
39: /lib/x86_64-linux-gnu/ [0x7f6eed59a516]
38: /lib/x86_64-linux-gnu/ [0x7f6eed59a516]
37: /lib/x86_64-linux-gnu/ [0x7f6eed59a516]
36: /lib/x86_64-linux-gnu/ [0x7f6eed59a490]
35: /lib/x86_64-linux-gnu/ [0x7f6eed59a490]
34: /lib/x86_64-linux-gnu/ [0x7f6eed5788d5]
33: /lib/x86_64-linux-gnu/ [0x7f6eed569f87]
32: /lib/x86_64-linux-gnu/ [0x7f6f46678f93]
31: /usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/ [0x7f6f18291408]
30: /lib/x86_64-linux-gnu/ [0x7f6f45a779a3]
29: /lib/x86_64-linux-gnu/ [0x7f6f45a7432b]
28: /lib/x86_64-linux-gnu/ [0x7f6f45a7524d]
27: /lib/x86_64-linux-gnu/ [0x7f6f467c2a09]
26: /lib/x86_64-linux-gnu/ [0x7f6f467c5b2a]
25: /lib/x86_64-linux-gnu/ [0x7f6f467c5ca6]
24: /lib/x86_64-linux-gnu/ [0x7f6f4679fe77]
23: /lib/x86_64-linux-gnu/ [0x7f6f467a5a7a]
22: /lib/x86_64-linux-gnu/ [0x7f6f46679562]
21: /lib/x86_64-linux-gnu/ [0x7f6f4667aeb5]
20: /lib/x86_64-linux-gnu/ [0x7f6f4667b921]
19: /lib/x86_64-linux-gnu/ [0x7f6f467aa2a4]
18: /lib/x86_64-linux-gnu/ [0x7f6f46679562]
17: /lib/x86_64-linux-gnu/ [0x7f6f4667aeb5]
16: /lib/x86_64-linux-gnu/ [0x7f6f4667b921]
15: /lib/x86_64-linux-gnu/ [0x7f6f467a6fec]
14: /lib/x86_64-linux-gnu/ [0x7f6f46679562]
13: /lib/x86_64-linux-gnu/ [0x7f6f4667b5c4]
12: /lib/x86_64-linux-gnu/ [0x7f6f4667b8f9]
11: /lib/x86_64-linux-gnu/ [0x7f6f467a73bd]
10: /lib/x86_64-linux-gnu/ [0x7f6f467a74ca]
9: ./Rack(osdialog_file+0x8e) [0x5be31a]
8: ./Rack(_ZN4rack12PatchManager12saveAsDialogEv+0x113) [0x540535]
7: ./Rack(_ZN4rack3app5Scene10onHoverKeyERKNS_5event8HoverKeyE+0x28a) [0x5a8e0e]
6: ./Rack(_ZN4rack5event5State9handleKeyENS_4math3VecEiiii+0x1dd) [0x56cdb3]
5: ./Rack() [0x566498]
4: ./Rack(_glfwPlatformPollEvents+0xbe7) [0x5cf4f0]
3: ./Rack(_ZN4rack6Window3runEv+0x69) [0x5666bb]
2: ./Rack(main+0x45a) [0x4e6e1a]
1: /lib/x86_64-linux-gnu/ [0x7f6f46016b6b]
0: ./Rack(_start+0x29) [0x4ebd49]

Does anyone have any idea what might be causing this? I’m really quite stumped :thinking::thinking::thinking:

It’s a bit hard to track this down without access to the source, but I’ll try: running Rack with a debugger I get a segmentation fault if I delete any second instance of Chronoblob2. It happens while deconstructing module’s widget, so my guess is that in the deconstructor of Chronoblob2’s widget is something deleted that shouldn’t. Can you check that?

There’s not really enough to point to the cause, but bizarre crashes that follow a specific sequence of events but aren’t directly related to those events often mean memory corruption. Run it under Valgrind and you might find it points you to the problem.

I’ve seen crashes like this in other software,and it looks like memory allocation problems. Probably a double free.

Use Valgrind to get a comprehensive look at memory errors. It will show the memory errors that lead up to the crash.

Just guessing, but if the crash is down in the SVG library, you’re not managing resources shared between module instances correctly.

my obvious guess:
it’s a global/singleton allocated in global space at the first use and deallocate in the destructor without setting at least to NIL the pointer : other instances still using it crash

Thank you all for the suggestions! I’m running valgrind right now but it sure is slow. I’ll follow up with those results.

@stoermelder My widget doesn’t define a destructor, so it should just have the empty one inherited from ModuleWidget right?

@chaircrusher @synthi There’s only one place where I’ve used dynamic memory, and it isn’t shared between instances. It’s in the following class. Have I screwed up the memory management?

template <typename T>
class RamMemory
    T *buffer_;
    uint32_t buffer_size_;
    uint32_t head_;

        buffer_ = NULL;

        delete[] buffer_;

    void Init(uint32_t size, uint32_t initial_head_position = 0)
        delete[] buffer_;
        buffer_ = new T[size];
        buffer_size_ = size;
        head_ = initial_head_position;
        memset(buffer_, 0, buffer_size_ * sizeof(T));

    void Write(T *source, uint32_t length)
        if (head_ + length <= buffer_size_)
            memcpy(&buffer_[head_], source, length * sizeof(T));

            head_ += length;
            head_ %= buffer_size_;
            uint32_t length_a = buffer_size_ - head_;
            uint32_t length_b = length - length_a;

            memcpy(&buffer_[head_], source, length_a * sizeof(T));
            memcpy(buffer_, &source[length_a], length_b * sizeof(T));

            head_ = length_b;

    void Read(T *dest, uint32_t delay, uint32_t length)
        uint32_t offset = head_;

        if (head_ < delay)
            offset += buffer_size_;

        offset -= delay;

        if (offset + length <= buffer_size_)
            memcpy(dest, &buffer_[offset], length * sizeof(T));
            uint32_t length_a = buffer_size_ - offset;
            uint32_t length_b = length - length_a;

            memcpy(dest, &buffer_[offset], length_a * sizeof(T));
            memcpy(&dest[length_a], buffer_, length_b * sizeof(T));

seems correct, only problem is not thread safe: one thread could be writing when another one (the owner of the object) is calling the destructor

But I guess this is all in the engine thread

Wouldn’t that class also have problems if you copied it (since the copy would copy the pointer and delete it twice) and also if you never called init on one, in which case it would delete[] null? Or am I misreading the code?

Here’s a modified version of the RamMemory code in an example which does the double free and, on my mac, shows a pretty clear memory error

#include <iostream>

template <typename T>
class RM
   T *b;
   RM() { b = nullptr; }
   ~RM() { 
     std::cout << "Deleting memory at " << (size_t)b << std::endl;
     delete[] b; 
   void init() {
     b = new T[123];

int main(int argc, char **argv)
    RM<float> B; B.init();
    // Will delete NULL
    RM<float> B; 
    RM<float> B; B.init(); RM<float> C; C = B;
    // Will double delete.

Pretty easy to fix, though, if you just #include <memory> and make T* buffer_ a std::shared_ptr<T> buffer_ or what not.

Deleting a null pointer has no effect. That makes sense about the double deletion but I’m not copying this class anywhere.

I tried running under valgrind but I gave up after a couple days. I know it’s supposed to run slowly but it took literal hours just to finish drawing the 2 modules in my patch. Is that normal?

if you’re using clang++ or g++ 4.8 or higher you can add -fno-omit-frame-pointer -fsanitize=address to your flags, which will do run-time checking.

Should I use those flags to compile Rack or my plugin? Or both? I tried compiling the plugin with them but then Rack could not find any modules in the plugin.

your plugin, but depending on your OS, you might need to dyload some libraries when it runs. check the output of your logs when you ./Rack -d.

Well I finally had time to chase down this bug. Turns out @synthi was exactly right. I had one global that I was using to store a pointer. Simply replaced it with a class member and no more crashing! The commit diff was like 2 lines, lmao. Embarrassing :stuck_out_tongue:

Anyway thank you so much everyone for your help and suggestions!


Hi @AlrightDevices, I think I’ve got a similar issue in a plugin I’ve just been testing.

If it’s okay could you please copy those commit diff lines into this thread? I’m struggling to fully grasp what your solution was. I’m hoping it will be a similar fix for my plugin!


I don’t think the commit diff by itself will help. It’s better if I just describe the problem and solution.

I have a class called Interface whose source is split into an .h file and a .cpp file. My Module class contains a member of type Interface. Interface has no static members, but there was a global variable instantiated in the .cpp file, separate from the class.

Interface was using that variable to store a pointer to another member of its owner Module during initialization, and to dereference later during runtime. Since the pointer was global, it was shared between instances of Interface, and therefore also between instances of Module.

So, consider this sequence of events:

  • Instantiate a Module called module1. Now global_pointer contains the address of module1.other_member. Everything is fine.

  • Instantiate a Module called module2. Now global_pointer contains the address of module2.other_member. Both module1.interface and module2.interface are dereferencing a pointer to module2.other_member. This is not good but it probably won’t cause a crash, although it might cause some weird interaction between the two instances. In my case it didn’t have any effect because of the nature and purpose of other_member.

  • Destruct module2. Now module1.interface is still dereferencing a pointer to module2.other_member, which has been deallocated. Oops!

The solution is simple, just get rid of the global variable and store the pointer in a member variable instead.

Hope that helps! Good luck!


Much appreciated! Hmmm, i think I’ve removed all global pointers. I do have some 2d vectors… perhaps it is them?

The process you outline to replicate your crash works for me so I reckon I’m on the right track…

I’ll keep digging :slight_smile:


@AlrightDevices - Hi Tyler,

I’ve been playing around with your plugin. Really love it.

One interesting thing I’ve noticed is that when I use my plugin in tandem with others, occasionally it will cause rendering to mess up on multiple plugins, including itself… This may well be a separate issue from what I’ve been attempting to troubleshoot but I thought I’d post a screenshot to see if it rings any bells in what you’ve worked though. This is how your Chronoblob2 is affected:

Again, I’m almost certain it is my plugin causing this graphical tearing effect on yours somehow…

It is less obvious on my plugin due to the colours I’ve used but it’s still there. (tear of block colour from top left to the bottom right):

If this is not something you’ve seen before then not to worry. Just mildly hopeful that it may somehow correlate with the saving/segfault that my module is still suffering from.


I saw this once before in a stoemelder plug :

And @stoermelder knew what to do, maybe its related ?

1 Like

Thanks @Yeager, I’ll follow the link shortly. :crossed_fingers::+1:

I had an array-out-of-bounds access in my module that caused visual destruction…

1 Like