ChildProcess::start failing with spaces in the path

Hi,

I'm launching a command-line program (Perforce) from within a JUCE application and want to process the output of that program.  I do this by creating a ChildProcess and calling start() on it, then periodically calling readProcessOutput() to update a string containing the resulting output.  I do this rather than calling readAllProcessOutput() because some commands take a while to complete so I run this in another thread and pass the updates back to the GUI thread via a message.

I place the filename of the executable in quotes to safe-guard against spaces in the path, and this works on Windows but on OSX I am experiencing a problem.  If the path to the executable includes a space, the call to start() doesn't return an error, but the child process fails to launch and the output contains a stream of JUCE errors from the LeakedObjectDetector.

This same error occurs if the program being launched can't be found.  I've put a check in my code for missing programs, but there are some programs I need to call that include a space in the path.  Does anybody know a way of working around this?

Thanks,

Charles

You shouldn't actually need to add quotes - the classes should add them for you if it needs them.

The leaks sound a bit strange though - can you give us some sample code that reproduces the problem?

Using the Helloworld example, I placed the following code in the HelloWorldWindow constructor, right at the end, just after the call to setVisible():

        ChildProcess cp;
        cp.start( "invalid_command" );
        String sOutput = cp.readAllProcessOutput();
        Logger::outputDebugString( sOutput );

The only other change I made was to set the Deployment Target to 10.8 (as that's the version of OSX I'm running on).

Hmm.. tried it here and no leaks. There's also nothing in the code that looks like it could leak. I think maybe in your code you're somehow exiting before the ChildProcess object is deleted?

Hi Jules,

Thanks for checking.  I've just tested and it's the same with our raw code drop for me, but it looks like we haven't updated since September last year.  I'll get the latest version and try again.

Charles

Hi, 

I've just downloaded the current build from GitHub and made the same change as I mentioned above, and this is the output I get:

JUCE v3.1.1
*** Leaked objects detected: 1 instance(s) of class ActiveProcess
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class ChildProcess
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 2 instance(s) of class OSXTypeface
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 2 instance(s) of class Typeface
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class TextButton
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class Label
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class Font
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class TypefaceCache
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class MainComponent
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class KeyPress
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class OwnedArray
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class ButtonListenerProxy
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 3 instance(s) of class GlassWindowButton
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 4 instance(s) of class CallbackHelper
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 4 instance(s) of class Button
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 5 instance(s) of class SimpleValueSource
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 5 instance(s) of class ValueSource
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 7 instance(s) of class Path
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class LookAndFeel_V2
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class LookAndFeel
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class DocumentWindow
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class ResizableWindow
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class ComponentBoundsConstrainer
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class ComponentDragger
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class TimerThread
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class Thread
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 3 instance(s) of class WaitableEvent
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class NSViewComponentPeer
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class ComponentPeer
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class DisplaySettingsChangeCallback
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class Desktop
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class ComponentAnimator
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class OwnedArray
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class MouseInputSource
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class MouseInputSourceInternal
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class OwnedArray
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 10 instance(s) of class AsyncUpdater
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class TopLevelWindow
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 7 instance(s) of class Component
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 7 instance(s) of class MouseCursor
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class ApplicationCommandTarget
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class MessageManager
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class Image
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 2 instance(s) of class AffineTransform
JUCE Assertion failure in juce_LeakedObjectDetector.h:95
*** Leaked objects detected: 1 instance(s) of class StringArray
JUCE Assertion failure in juce_LeakedObjectDetector.h:95

I'm running on OSX 10.8.5 with XCode 5.0.1 and other than change the Deployment Target to 10.8 I've made no other changes to the JUCE code.

I've bypassed my original problem by swapping to use the StringArray version of ChildProcess::start() but that doesn't fix the underlying issue.

Charles

Nope, I tried that code in the hello world app, and had no leaks.

That log means that your app isn't actually shutting down properly or deleting its window. You must be doing something that you've not mentioned in this thread to cause it to quit suddenly or not clean up.

While trying to set up a minimal PIP that reproduces the error I reported in this thread Error running JUCE application with ChildProcess under Xcode Instruments profiler, I was running into the same error that was described in this thread. This PIP

/*******************************************************************************
 The block below describes the properties of this PIP. A PIP is a short snippet
 of code that can be read by the Projucer and used to generate a JUCE project.

 BEGIN_JUCE_PIP_METADATA

  name:             ChildProcessProfilerBug

  dependencies:     juce_core
  exporters:        xcode_mac

  type:             Console

 END_JUCE_PIP_METADATA

*******************************************************************************/

#pragma once


//==============================================================================
int main (int argc, char* argv[])
{

    ChildProcess childProcess;
    
    bool success = childProcess.start ("invalid_command");
    
    if (!success)
    {
        std::cerr << "No success starting child process" << std::endl;
        return 1;
    }

    std::cout << "Process output: " << childProcess.readAllProcessOutput() << std::endl;

    return 0;
}

produces the following console output:

JUCE v5.4.1
Process output: *** Leaked objects detected: 1 instance(s) of class ActiveProcess
JUCE Assertion failure in juce_LeakedObjectDetector.h:90
*** Leaked objects detected: 1 instance(s) of class ChildProcess
JUCE Assertion failure in juce_LeakedObjectDetector.h:90
*** Leaked objects detected: 1 instance(s) of class StringArray
JUCE Assertion failure in juce_LeakedObjectDetector.h:90

Program ended with exit code: 0

Please note that this is the actual content of ChildProcess::readAllProcessOutput and NOT a usual print from the leak detector.

This does not happen when passing in some very usual commands like pwd however this also happens when invoking other, normally valid commands that run successfully when calling them by hand in a terminal. Although this is not the error I encountered originally in the thread I linked above, this is a quite confusing to me right now as it opens up another error while trying to track down a different bug. Any thoughts on this?

I tried to track it down a bit. I could find that while being empty/uninitialized before, after the call to fread here the string buffer (where the dest void pointer points to) filled by fread contains the Leak Detector strings

I don’t really understand what’s going on there, to me it seems like some uninitialized previously filled memory is read again there? By the way, after running it a few times, suddenly the string returned was just empty and I was not able to reproduce the bug anymore but the it suddenly re-appeared.