mrray's picture

Status: 

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.