jstrecker's picture

Jaymie (@jstrecker)


  • Vuo Founder
  • Team Vuo
jstrecker's picture
Jaymie commented on wmackwood's Bug Report, “trouble with sub-compositions . . .

There's definitely something going wrong here. When I exported your composition to app, the app consistently crashed on launch. We'll investigate.

Thanks for taking the time to test the beta version and report problems, so that we can make the final release more stable.

jstrecker's picture

mrray — I tried your code above and got the same result (no crash for static allocation). That is indeed odd… but I think the static allocation only masks the problem.

If I change the static-allocation version slightly, then it does crash —

VuoCompilerIssues issues;  // this line added
VuoCompiler     tmpCompiler(inCompPath);

There must be a memory bug somewhere, but I haven't tracked it down yet. If you have any other ideas or observations, let me know.

By the way, the compileComposition function expects a non-null argument (e.g. &issues) — but that's not the cause of this particular crash.

jstrecker's picture
Jaymie commented on Chris's Bug Report, “Audio Device has no channels - Solved

Glad to hear that It's working now.

I created a separate bug report for the question about Get Audio Input Values: https://vuo.org/node/2461

jstrecker's picture
Jaymie commented on prackvj's Bug Report, “Unexpectedly quit(s)...

prackvj, thanks for reporting this crash. We'll have it fixed in the final Vuo 2.0.0 release.

In case anyone else looking at this bug report is wondering if they have the same problem, here's how we reproduced the crash:

  1. Create a new composition
  2. Detach a popover
  3. Close the composition
  4. Repeat above steps
  5. Hide Vuo Editor (⌘H) — crash
jstrecker's picture

I noticed that part of your code in -[VuoHolder compileAndLoadComp:] was very similar to VuoCompiler::newCurrentProcessRunnerFromCompositionFile(). So I tried replacing the relevant part with this:

VuoCompilerIssues issues;
runner = VuoCompiler::newCurrentProcessRunnerFromCompositionFile(inCompPath, &issues)

And that seems to avoid the crash.

But I still don't understand why. And since newCurrentProcessRunnerFromCompositionFile does differ somewhat from your code, I'm not sure if it would adequately solve your problem or not.

I compared your code to newCurrentProcessRunnerFromCompositionFile. Here's the source code as of 2.0.0-beta1:

VuoRunner * VuoCompiler::newCurrentProcessRunnerFromCompositionFile(string compositionFilePath, VuoCompilerIssues *issues)
        VuoCompiler compiler(compositionFilePath);
        string directory, file, extension;
        VuoFileUtilities::splitPath(compositionFilePath, directory, file, extension);
        string compiledCompositionPath = VuoFileUtilities::makeTmpFile(file, "bc");
        compiler.compileComposition(compositionFilePath, compiledCompositionPath, true, issues);
        string linkedCompositionPath = VuoFileUtilities::makeTmpFile(file, "dylib");
        compiler.linkCompositionToCreateDynamicLibrary(compiledCompositionPath, linkedCompositionPath, Optimization_FastBuild);
        return VuoRunner::newCurrentProcessRunnerFromDynamicLibrary(linkedCompositionPath, directory, true);
    catch (VuoCompilerException &e)
        if (issues != e.getIssues())
        return NULL;

I also compared your code to -[VuoRunnerCocoa compileAndRun]:

- (void)compileAndRun
    [VuoRunnerCocoa prepareForFastBuild];
    dispatch_sync(self.runnerQueue, ^{
        VuoCompilerIssues issues;
        if (self.compositionURL)
            self.runner = VuoCompiler::newSeparateProcessRunnerFromCompositionFile(
                [[self.compositionURL path] UTF8String],
            self.runner = VuoCompiler::newSeparateProcessRunnerFromCompositionString(
                [self.compositionString UTF8String],
                [self.compositionProcessName UTF8String],
                [self.compositionSourcePath UTF8String],
        if (!issues.isEmpty())
            VUserLog("%s", issues.getLongDescription(false).c_str());
        if (self.runner)
                vector<VuoRunner::Port *> allInputPorts = self.runner->getPublishedInputPorts();
                std::copy_if(allInputPorts.begin(), allInputPorts.end(), std::inserter(*self.changedPorts, self.changedPorts->begin()),
                          [] (VuoRunner::Port *port) { return ! port->getType().empty(); });
            catch (VuoException &e)
                VUserLog("Error: %s", e.what());

After trying numerous changes to your code, I still haven't figured it out. If you have any ideas, please let me know.