Param Quantity/Param Widget Null Module (Solved)

Hi everyone,

I’m getting a null module crash in my plugin from the module widget. It doesn’t always happen, but it does always happen if I duplicate the module ~2-4 times. It also happens about 15% of the time I add the module from the module window.

Relevant Log Contents
[6.773 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[6.773 warn src/GreatSandDunes.cpp:249 step] Module is null
[6.773 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[6.808 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[6.808 warn src/GreatSandDunes.cpp:249 step] Module is null
[6.808 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[6.841 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[6.842 warn src/GreatSandDunes.cpp:249 step] Module is null
[6.842 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[6.875 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[6.875 warn src/GreatSandDunes.cpp:249 step] Module is null
[6.875 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[6.909 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[6.910 warn src/GreatSandDunes.cpp:249 step] Module is null
[6.910 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[6.944 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[6.944 warn src/GreatSandDunes.cpp:249 step] Module is null
[6.944 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[6.978 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[6.978 warn src/GreatSandDunes.cpp:249 step] Module is null
[6.978 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[7.011 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[7.011 warn src/GreatSandDunes.cpp:249 step] Module is null
[7.011 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[7.045 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[7.045 warn src/GreatSandDunes.cpp:249 step] Module is null
[7.045 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[7.080 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[7.080 warn src/GreatSandDunes.cpp:249 step] Module is null
[7.080 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[7.113 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[7.113 warn src/GreatSandDunes.cpp:249 step] Module is null
[7.113 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[7.146 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[7.146 warn src/GreatSandDunes.cpp:249 step] Module is null
[7.146 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[7.180 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[7.180 warn src/GreatSandDunes.cpp:249 step] Module is null
[7.180 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[7.214 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[7.215 warn src/GreatSandDunes.cpp:249 step] Module is null
[7.215 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[7.249 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[7.249 warn src/GreatSandDunes.cpp:249 step] Module is null
[7.249 info src/GreatSandDunes.cpp:251 step] Exiting GreatSandDunesWidget::step()
[7.282 info src/GreatSandDunes.cpp:235 step] Entering GreatSandDunesWidget::step()
[7.282 warn src/GreatSandDunes.cpp:249 step] Module is null

I saw this post: After upgrade to v1, Issues with paramQuantity and ParamWidget

I think it’s the same issue, but I didn’t really see a solution. What should I be doing differently? This is what I have. I’m confused because it’s set up the same as all my other modules, but this is the only one that is causing a problem. It was also causing a problem before I added the interpolation light button. LLDB backtrace doesn’t really seem to show anything different from what the log is already saying and I’m not sure what else to do with it beyond the backtrace.

LLDB
Process 48882 launched: '/Applications/VCV Rack 2 Free.app/Contents/MacOS/Rack' (x86_64)
2024-06-11 11:10:33.435529-0400 Rack[48882:7703689] [plugin] AddInstanceForFactory: No factory registered for id <CFUUID 0x6000001825c0> F8BB1C28-BAE8-11D6-9C31-00039315CD46
2024-06-11 11:10:37.615335-0400 Rack[48882:7703689] WARNING: Secure coding is automatically enabled for restorable state! However, not on all supported macOS versions of this application. Opt-in to secure coding explicitly by implementing NSApplicationDelegate.applicationSupportsSecureRestorableState:.
2024-06-11 11:10:42.862801-0400 Rack[48882:7703900] [StateRestoration] BOOL _NSPersistentUIDeleteItemAtFileURL(NSURL *const __strong) Failed to stat item: file:///Users/josiahsytsma/Library/Saved%20Application%20State/com.vcvrack.rack.savedState/restorecount.plist
Process 48882 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x0000000000000000
error: memory read failed for 0x0
Target 0: (Rack) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x0000000000000000
    frame #1: 0x0000000101acac5a libRack.dylib`rack::widget::Widget::step() + 58
    frame #2: 0x0000000101acac5a libRack.dylib`rack::widget::Widget::step() + 58
    frame #3: 0x0000000101acac5a libRack.dylib`rack::widget::Widget::step() + 58
    frame #4: 0x0000000101acac5a libRack.dylib`rack::widget::Widget::step() + 58
    frame #5: 0x0000000101acac5a libRack.dylib`rack::widget::Widget::step() + 58
    frame #6: 0x0000000101acac5a libRack.dylib`rack::widget::Widget::step() + 58
    frame #7: 0x0000000101ac46a3 libRack.dylib`rack::ui::ScrollWidget::step() + 19
    frame #8: 0x0000000101a7b1bb libRack.dylib`rack::app::RackScrollWidget::step() + 667
    frame #9: 0x0000000101acac5a libRack.dylib`rack::widget::Widget::step() + 58
    frame #10: 0x0000000101a8749f libRack.dylib`rack::app::Scene::step() + 431
    frame #11: 0x0000000101ad0074 libRack.dylib`rack::window::Window::step() + 1716
    frame #12: 0x0000000101acf9a8 libRack.dylib`rack::window::Window::run() + 40
    frame #13: 0x000000010000274b Rack`main + 4443
    frame #14: 0x00007ff80177d366 dyld`start + 1942
(lldb) 

This is my widget source if it helps. The atomic pointer was a shot in the dark because I am out of ideas and I wanted to see what might happen.

struct GreatSandDunesWidget : ModuleWidget {
    std::atomic<GreatSandDunes*> atomic;
    
    GreatSandDunesWidget(GreatSandDunes* module) {
        setModule(module);
        setPanel(createPanel(asset::plugin(pluginInstance, "res/Light/SandDunes.svg"), asset::plugin(pluginInstance, "res/Dark/SandDunes.svg")));
        
        addChild(createWidget<ThemedScrew>(Vec(RACK_GRID_WIDTH, 0)));
        addChild(createWidget<ThemedScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
        addChild(createWidget<ThemedScrew>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
        addChild(createWidget<ThemedScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
        
        if (module) {
            atomic.store(module);
            addParam(createParamCentered<RoundHugeBlackKnob>(mm2px(Vec(11.637, 30.718)), module, GreatSandDunes::DOWNSAMPLE_PARAM));
            addParam(createParamCentered<RoundHugeBlackKnob>(mm2px(Vec(34.083, 30.718)), module, GreatSandDunes::BITCRUSH_PARAM));
            addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(22.86, 53.343)), module, GreatSandDunes::CUTOFF_PARAM));
            addParam(createParamCentered<Trimpot>(mm2px(Vec(6.522, 72.111)), module, GreatSandDunes::DOWNSAMPLE_CV_PARAM));
            addParam(createParamCentered<Trimpot>(mm2px(Vec(17.221, 72.111)), module, GreatSandDunes::BITCRUSH_CV_PARAM));
            addParam(createParamCentered<Trimpot>(mm2px(Vec(28.418, 72.111)), module, GreatSandDunes::CUTOFF_CV_PARAM));
            addParam(createLightParamCentered<VCVLightLatch<MediumSimpleLight<WhiteLight>>>(mm2px(Vec(39.157, 82.841)), module, GreatSandDunes::INTERP_PARAM, GreatSandDunes::INTERP_LIGHT));
            
            //        addParam(createLightParamCentered<VCVLightLatch<MediumSimpleLight<WhiteLight>>>(mm2px(Vec(17.221, 97.076)), module, GreatSandDunes::INTERP_PARAM, GreatSandDunes::INTERP_LIGHT)); // Moved button to where the input was
            
            addInput(createInputCentered<ThemedPJ301MPort>(mm2px(Vec(6.563, 82.841)), module, GreatSandDunes::DOWNSAMPLE_INPUT));
            addInput(createInputCentered<ThemedPJ301MPort>(mm2px(Vec(17.261, 82.841)), module, GreatSandDunes::BITCRUSH_INPUT));
            addInput(createInputCentered<ThemedPJ301MPort>(mm2px(Vec(28.459, 82.841)), module, GreatSandDunes::CUTOFF_INPUT));
            addInput(createInputCentered<ThemedPJ301MPort>(mm2px(Vec(6.522, 97.075)), module, GreatSandDunes::IN_INPUT));
            
            //        addInput(createInputCentered<PJ301MPort>(mm2px(Vec(39.157, 82.841)), module, GreatSandDunes::INTERP_INPUT));
            
            addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(28.418, 97.075)), module, GreatSandDunes::DC_OUTPUT));
            addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(39.117, 97.076)), module, GreatSandDunes::CD_OUTPUT));
        }
        else {
            WARN("GreatSandDunesWidget constructed with null module pointer");
            atomic.store(nullptr);
        }
    }
    
    void step() override {
        INFO("Entering GreatSandDunesWidget::step()");
        GreatSandDunes* sandDunesModule = atomic.load();
        if (sandDunesModule) {
            INFO("Module found: %p", sandDunesModule);
            sandDunesModule->lights[GreatSandDunes::INTERP_LIGHT].setBrightness(sandDunesModule->interp);
        } else {
            WARN("Module is null");
        }
        INFO("Exiting GreatSandDunesWidget::step()");
        ModuleWidget::step();
    }
};


Model* modelGreatSandDunes = createModel<GreatSandDunes, GreatSandDunesWidget>("GreatSandDunes");

Null module is normal. There is no module when instantiated for the module browser, so all code must be tolerant of a null module.

1 Like

The atomic does nothing for you here.

Sure. That was a last ditch attempt to try to fix it. I took the useless atomic out shortly after. And I misspoke, it’s not that it’s null, it’s that it’s trying to access something invalid and Rack is crashing. I tried

void step() override {
        if(module != NULL){
            ModuleWidget::step();
            GreatSandDunes *dunes = dynamic_cast<GreatSandDunes*>(module);
            dunes->lights[GreatSandDunes::INTERP_LIGHT].setBrightness(dunes->interp);
        }
    }

which also didn’t help. I don’t know what’s causing the SIGABRT though…

This is embarrassing. I found the issue.

if (!inputs[IN_INPUT].isConnected()) {
            for (int i = 0; i < INPUTS_LEN; i++)
                outputs[i].setVoltage(0);
            return;
        }

Changed INPUTS_LEN to OUTPUTS_LEN and viola :man_facepalming:

2 Likes