mrray's picture

Status: 

Vuo version: 

Fixed in Vuo version: 

OS version: 

  • macOS 10.13

How severely does this bug affect you?: 

●●●○ — It prevents me from completing a specific task with Vuo.

Steps causing the bug to occur: 

  • sample project included, build & run
  • alternate between clicking "Load 1st comp" and "Load 2nd comp" buttons until the app crashes.
  • crash is 100% reproducible on every machine we've tested so far.
  • crash almost always occurs within the first cycle or two (usually on 2nd click).
  • crash doesn't occur with the 2.0 alpha (2.0.0.10623)- only reproducible using the 2.0 public beta (2.0.0.10830).
  • stack usually looks something like this:

  • 0 0x00007fff58242b66 in __pthread_kill ()
  • #1 0x00000001053c10f0 in pthread_kill ()
  • #2 0x00007fff5819e1ae in abort ()
  • #3 0x00007fff582ade3d in nanozone_error ()
  • #4 0x00007fff582a1dde in _nano_malloc_check_clear ()
  • #5 0x00007fff582a1c23 in nano_malloc ()
  • #6 0x00007fff5829b241 in malloc_zone_malloc ()
  • #7 0x00007fff5829a5bf in malloc ()
  • #8 0x00007fff56099628 in operator new(unsigned long) ()
  • #9 0x00007fff5607ffc9 in std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >::__init(char const*, unsigned long, unsigned long) ()
  • #10 0x000000010040b969 in std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > std::__1::operator+<char, std::__1::char_traits, std::__1::allocator >(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, char const*) ()
  • #11 0x00000001003ab4cf in VuoCompiler::VuoCompiler(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&) ()
  • #12 0x0000000100001877 in ::-[VuoHolder compileAndLoadComp:](NSString *) at /Users/testadmin/Documents/VuoQuestions6/VuoHolder.mm:50
  • #13 0x000000010000fb57 in ::__37-[AppDelegate loadSecondCompClicked:]_block_invoke() at /Users/testadmin/Documents/VuoQuestions6/VuoQuestions6/AppDelegate.mm:63

Have you found a workaround?: 

nope, sorry!

Comments

I noticed that part of your

jstrecker's picture
Submitted by

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)
{
    try
    {
        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);
        remove(compiledCompositionPath.c_str());
        return VuoRunner::newCurrentProcessRunnerFromDynamicLibrary(linkedCompositionPath, directory, true);
    }
    catch (VuoCompilerException &e)
    {
        if (issues != e.getIssues())
            issues->append(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],
                &issues);
        else
            self.runner = VuoCompiler::newSeparateProcessRunnerFromCompositionString(
                [self.compositionString UTF8String],
                [self.compositionProcessName UTF8String],
                [self.compositionSourcePath UTF8String],
                &issues);
 
        if (!issues.isEmpty())
            VUserLog("%s", issues.getLongDescription(false).c_str());
 
        if (self.runner)
        {
            self.runner->start();
            self.runner->subscribeToEventTelemetry("");
 
            try
            {
                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.

hi jaymie-

mrray's picture
Submitted by

hi jaymie-

i think i may have narrowed it down a bit- it seems like an issue with how VuoCompiler is created (stack vs heap)?

this code crashes:

- (void) compileAndLoadComp:(NSString *)inPath  {
    [self _eject];

    pthread_mutex_lock(&runnerLock);

    loadDate = [[NSDate date] retain];

    string      inCompPath = string([inPath UTF8String]);
    string      filename = string([[[NSUUID UUID] UUIDString] UTF8String]);
    string      binPath = "/tmp/" + filename + ".bc";
    string      dylibPath = "/tmp/" + filename + ".dylib";
    cout << "dylibPath is " << dylibPath << endl;

    VuoCompiler     *tmpCompiler = new VuoCompiler(inCompPath);
    tmpCompiler->setCompositionPath(inCompPath);
    tmpCompiler->compileComposition(inCompPath, binPath, true, nullptr);
    tmpCompiler->linkCompositionToCreateDynamicLibrary(binPath, dylibPath, VuoCompiler::Optimization_FastBuild);
    delete tmpCompiler;

    runner = VuoRunner::newCurrentProcessRunnerFromDynamicLibrary(dylibPath, "/tmp", false);

    [self _startComp];

    pthread_mutex_unlock(&runnerLock);
}

this code does not crash:

- (void) compileAndLoadComp:(NSString *)inPath  {
    [self _eject];

    pthread_mutex_lock(&runnerLock);

    loadDate = [[NSDate date] retain];

    string      inCompPath = string([inPath UTF8String]);
    string      filename = string([[[NSUUID UUID] UUIDString] UTF8String]);
    string      binPath = "/tmp/" + filename + ".bc";
    string      dylibPath = "/tmp/" + filename + ".dylib";
    cout << "dylibPath is " << dylibPath << endl;

    VuoCompiler     tmpCompiler(inCompPath);
    tmpCompiler.setCompositionPath(inCompPath);
    tmpCompiler.compileComposition(inCompPath, binPath, true, nullptr);
    tmpCompiler.linkCompositionToCreateDynamicLibrary(binPath, dylibPath, VuoCompiler::Optimization_FastBuild);

    runner = VuoRunner::newCurrentProcessRunnerFromDynamicLibrary(dylibPath, "/tmp", false);

    [self _startComp];

    pthread_mutex_unlock(&runnerLock);
}

mrray — I tried your code

jstrecker's picture
Submitted by

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.

We found the cause of the

jstrecker's picture
Submitted by
Status:
Waiting for review by Vuo Support Team
»
Accepted

We found the cause of the problem! Because of how our build system works, the VuoCompiler class declaration used when compiling Vuo.framework differs slightly from the header file packaged with Vuo.framework. This messes up the allocation of VuoCompiler in your Xcode project.

It's possible to reproduce the problem with a simple program that links to Vuo.framework, one that just calls new VuoCompiler(). This may run just fine under normal testing. But if you enable Guard Malloc (in Xcode: Edit Scheme > Diagnostics), it consistently crashes at the very beginning of the VuoCompiler constructor.

Thanks for alerting us to this problem, mrray. We'll have it fixed by the final Vuo 2.0.0 release.