Help needed closing NSPipe

I’m working on an app that creates compressed disk images using dd and gzip. I have set up a working pipe between dd and gzip NSTask’s but I cannot figure out how to close the pipe. When the dd process completes, the pipe stays open and gzip continues to wait for more data. How can I close the pipe or the pipe’s fileHandleForWriting so that gzip receives the EOF it needs to terminate successfully?

Here’s a working abridged copy of the app code:

script AppDelegate
	property parent : class "NSObject"
    property NSPipe : class "NSPipe"
    property NSNotificationCenter : class "NSNotificationCenter"
    property ddTask : missing value
    property gzipTask :missing value
    property applicationPipe : missing value
    property pipeHandle : missing value
    property appTargetFileForWriting : missing value
    property theButton : missing value
	-- IBOutlets
	property theWindow : missing value
	on applicationWillFinishLaunching_(aNotification)
		-- Insert code here to initialize your application before any files are opened 
	end applicationWillFinishLaunching_
    on buttonClicked_(sender)
        log "button click registered"
        theButton's setEnabled_(0)
        set fileManager to current application's NSFileManager's defaultManager()
            fileManager's createFileAtPath_contents_attributes_("/tmp/test.img.gz", missing value, missing value)
            log "target file created"
        on error
            log "file creation error"
        end try
            set appTargetFileForWriting to current application's NSFileHandle's fileHandleForWritingAtPath_("/tmp/test.img.gz")
            log "target file handle set"
        on error
            log "error creating file handle"
        end try
        set ddTask to current application's NSTask's alloc()'s init()
        set applicationPipe to NSPipe's pipe()
        ddTask's setLaunchPath_("/bin/dd")
        ddTask's setArguments_({"bs=4k","count=1000","if=/dev/random"})
        ddTask's setStandardOutput_(applicationPipe)
        NSNotificationCenter's defaultCenter()'s addObserver_selector_name_object_(me, "ddTerminationHandler:", "NSTaskDidTerminateNotification", ddTask)
        set gzipTask to current application's NSTask's alloc()'s init()
        gzipTask's setLaunchPath_("/usr/bin/gzip")
        gzipTask's setArguments_({"--verbose"})
        gzipTask's setStandardInput_(applicationPipe)
        gzipTask's setStandardOutput_(appTargetFileForWriting)
        NSNotificationCenter's defaultCenter()'s addObserver_selector_name_object_(me, "gzipTaskTerminationHandler:", "NSTaskDidTerminateNotification", gzipTask)
        ddTask's |launch|()
        gzipTask's |launch|()
    end buttonClicked_
    on ddTerminationHandler_(aNotification)
        log "DD task completed"
        --Close pipe here?
        NSNotificationCenter's defaultCenter()'s removeObserver_name_object_(me, "NSTaskDidTerminateNotification", missing value)
    end ddTerminationHandler_
    on gzipTaskTerminationHandler_(aNotification)
        log "gzip task completed"
        appTargetFileForWriting's closeFile()
        theButton's setEnabled_(1)
        NSNotificationCenter's defaultCenter()'s removeObserver_name_object_(me, "NSTaskDidTerminateNotification", missing value)
    end gzipTaskTerminationHandler_
    on applicationShouldTerminateAfterLastWindowClosed_(sender)
        return true
    end applicationShouldTerminateAfterLastWindowClosed_
	on applicationShouldTerminate_(sender)
        return current application's NSTerminateNow
	end applicationShouldTerminate_
end script

Sorry for the multiple posts. Was having network issues and must have created them trying to refresh the submission page.

The first thing you need to do is fix how you’re using properties. If you declare a property x, you set its value using “set my x…”. If you leave out the my, you just create a local variable of the same name.

And I can’t fathom what this line is trying to do:

set applicationPipe to current application's NSFileHandle's fileHandleForWriting()'s closeFile()

Apart from the above problem, fileHandleForWriting is a pipe method, not a file handle method.

And where you say “Close pipe here?”, you probably want:

my applicationPipe's fileHandleForWriting()'s closeFile()

Whoops. That was something I was testing. I’ve removed it from the code above.

Found the problem.

The following code in ddTask’s termination handler kills the all the termination handlers so “on gzipTaskTerminationHandler_(aNotification)” never runs.

NSNotificationCenter's defaultCenter()'s removeObserver_name_object_(me, "NSTaskDidTerminateNotification", missing value)

Should probably use something like this instead:

NSNotificationCenter's defaultCenter()'s removeObserver_name_object_(me, "NSTaskDidTerminateNotification", my ddtask)