Re: NSTask is intermittently failing to return results.

2011-03-18 Thread Jason Harris
> 
> Hi Jason
> 
> I haven't attempted to debug your code but I use NSTask extensively and have 
> experienced some of the problems you describe.
> 
> In each case I was not correctly handling the asynchronous availability of 
> data in the pipe ie: there is nothing wrong with the approach but 
> implementation is all.
> 
> In my case I found that the implementation detailed in the following sample 
> worked with great reliability on GC apps (search the xcode docs):
> 
> 
> This sample uses NSFileHandle - waitForDataInBackgroundAndNotify.
> This generates a single notification with all the available data - which may 
> or may not be suitable for your needs.
> 
> The sample above calls NSTask - waitUntilExit but that is only a detail I 
> think.
> 
> If this was my project I would instigate a branch that implemented the 
> approach detailed in CommandLineToolPlugin.m and see where that got me.
> It should have fewer moving parts at least.
> 
> Regards
> 
> Jonathan Mitchell
> 
> Developer
> Mugginsoft LLP
> http://www.mugginsoft.com


Hi Jonathan,

Thanks for looking at this! It's good to know I am not going crazy and there is 
some subtle thing I am doing wrong here...

Just to clarify you mean this example here:

http://developer.apple.com/library/mac/#samplecode/CommandLineTool/Listings/CommandLineToolPlugIn_m.html

for the CommandLineToolPlugin.m?

I hadn't  seen this approach at the end of using [task waitUntilExit] after you 
have set up the observers and notifications. I had seen in eg OpenFileKiller: 
http://cocoawithlove.com/2009/05/invoking-other-processes-in-cocoa.html and in 
https://bitbucket.org/snej/myutilities/src/tip/MYTask.m where a run loop is 
used. Ie something like:

- (void)launchTaskAndRunSynchronous
{
[task launch];

BOOL isRunning = YES;
while (isRunning && (!taskComplete || !outputClosed || !errorClosed))
{
isRunning =
[[NSRunLoop currentRunLoop]
runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
}
}

(Also just glancing at the code, I noticed a couple of really small things... 
the date at the top of CommandLineToolPlugin.m lists 2009 yet its using old 
style NS_DURING, NS_HANDLER, NS_ENDHANDLER which seems a little strange... but 
its not wrong or anything, just a little well strange. Also it looks like 
CommandLineToolPlugin.m sets [task setStandardInput:inPipe] whereas I have no 
input.. Again just small differences. I will have a play and get back to the 
group.)

Thanks!
   Jas

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: NSTask is intermittently failing to return results.

2011-03-18 Thread Jason Harris

On Mar 18, 2011, at 10:36 PM, jonat...@mugginsoft.com wrote:

> 
> On 18 Mar 2011, at 21:04, Jason Harris wrote:
>> 
>> 
>> Hi Jonathan,
>> 
>> Thanks for looking at this! It's good to know I am not going crazy and there 
>> is some subtle thing I am doing wrong here...
>> 
>> Just to clarify you mean this example here:
>> 
>> http://developer.apple.com/library/mac/#samplecode/CommandLineTool/Listings/CommandLineToolPlugIn_m.html
>> 
>> for the CommandLineToolPlugin.m?
> Yep.
> 
>> 
>> I hadn't  seen this approach at the end of using [task waitUntilExit] after 
>> you have set up the observers and notifications. I had seen in eg 
>> OpenFileKiller: 
>> http://cocoawithlove.com/2009/05/invoking-other-processes-in-cocoa.html and 
>> in https://bitbucket.org/snej/myutilities/src/tip/MYTask.m where a run loop 
>> is used. Ie something like:
>> 
>> - (void)launchTaskAndRunSynchronous
>> {
>>  [task launch];
>>  
>>  BOOL isRunning = YES;
>>  while (isRunning && (!taskComplete || !outputClosed || !errorClosed))
>>  {
>>  isRunning =
>>  [[NSRunLoop currentRunLoop]
>>  runMode:NSDefaultRunLoopMode
>>  beforeDate:[NSDate distantFuture]];
>>  }
>> }
>> 
> I don't see any reason not to use the NSTask implementation unless you 
> encounter any particular issues.
> 
>> (Also just glancing at the code, I noticed a couple of really small 
>> things... the date at the top of CommandLineToolPlugin.m lists 2009 yet its 
>> using old style NS_DURING, NS_HANDLER, NS_ENDHANDLER which seems a little 
>> strange... but its not wrong or anything, just a little well strange.
> Yes, a bit curious. Maybe its a rehash of something more archaic though the 
> revision notes don't specify this.

Well just to give some quick feedback... Surprisingly to me your suggested 
approach here seems to be working straight off the bat!!

Ie if in my code I just replace 

- (BOOL) waitTillFinished
{
// wait for task to exit:
while (![self shouldFinishUp])
{
// If the task is terminated we should set up a pending 
termination which will terminate in a bit. This catches some
// zombie NSTasks where either the outputData or errorData of 0 
were never posted..
BOOL terminated = ![task_ isRunning];
if (terminated && !pendingTermination_)
{
DebugLog(@"...Found terminated for %@ ...", [self 
commandLineString]);
[self setPendingTermination];
}

BOOL runLoopRan = [[NSRunLoop currentRunLoop] 
runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
if (!runLoopRan)
break;
if (!isFinished_)
DebugLog(@"...waitTillFinished still waiting for %@ 
...", [self commandLineString]);
}

[self finishUp];
DebugLog(@"...Exiting waitTillFinished for %@ ...", [self 
commandLineString]);
return (result_ == 0);
}


with 

- (BOOL) waitTillFinished
{
// wait for task to exit:
[task_ waitUntilExit];
DebugLog(@"...Exiting waitTillFinished for %@ ...", [self 
commandLineString]);
return (result_ == 0);
}

Along with some other tweaks (No longer call [self finishUp] in any form) then 
it works.

Thank you! Thank you! At least I have something to explore now. I don't know 
*why* this works since it seems to use a different approach to that of eg 
OpenFileKiller and MyTask but:
(i) The exceptions seem to be gone
(ii) There seems to be no dropped results.
(iii) The tasks seem to be exiting (ie no stuck processes...) (A stuck process 
is a sort of zombie process which just doesn't finish (but it turns out a 
zombie process has a defined meaning in unix and my stuck processes where not 
zombies...))

I'll investigate a bit more and try and boil down what was going on and post my 
findings back. If anyone else can shed some light on the reasons why this is 
happening I would be most grateful.

But in any case *Thank You Jonathan*!!!

Cheers,
  Jas___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: NSTask is intermittently failing to return results.

2011-03-18 Thread Jason Harris

On Mar 18, 2011, at 11:07 PM, Ken Thomases wrote:

> I would say that your "...IgnoringErrors" methods are masking a real problem, 
> and you shouldn't have written them let alone used them.  (By the way, you 
> didn't post them except incidentally in your screenshot.)

(Ahh yep. I didn't want to spam the group with lots and lots of code and 
headers and other bits. I tried to pick the "relevant" code and then provided 
the link to the sourcefiles on bitbucket...)  

And in answer to this I was grasping at straws and I didn't really write this 
code, I was trying this since it was recommended in some previous posts by 
others (I can post the references if you are interested).  In the end I think 
this @try @catch just served to not crash the app and return nil for the 
result... But you are right I am keenly interested in what is going wrong and 
how to remedy it. (As I said previously the error would manifest itself every 
so often which was of course very annoying, but now moving to the Moriarty 
style of things, the errors suddenly became quite noticeable.)


> The exception is saying that the file descriptor backing the 
> NSPipe/NSFileHandle has been closed.  Retrying after some time can only 
> result in the frameworks co-opting a new, unrelated file object that happened 
> to get the same file descriptor.  That would explain why your reads sometimes 
> never get any data -- you're reading from a completely different file object.

I am sorry, but can you explain the paragraph in more detail? (Just to be clear 
sometimes I never get the exception and yet it still drops data... So the ugly 
bit of the @catch is never hit but it still was dropping the data...)


> I'm not sure why the file descriptor is being closed.  It may be a framework 
> bug having to do with garbage collection.
> 
> I'd try creating the file descriptors manually with the pipe(2) system call.  
> Then, construct NSFileHandles from them with 
> -initWithFileDescriptor:theReadFD closeOnDealloc:NO.

Sorry just so I don't stuff this up can I ask you to give me the exact code 
here... or point me to an example of this?


> (Pass [NSFileHandle fileHandleWithNullDevice] to -setStandardInput:, while 
> you're at it.)  After you launch the task, be sure to close the write ends of 
> your pipes.  And, of course, when everything is finished up, close the read 
> ends, too.

I'd like to try this thanks!


> By the way, there's nothing incorrect about getting the task-terminated 
> notification before the end-of-file for the task output or error file 
> handles.  There's no guarantee about the order of those events.

Yes, I gathered that. I also gathered that you should always get all three 
things right? ie
(i) The NSTaskDidTerminateNotification
(ii) and the NULL for the NSFileHandleReadCompletionNotification for stdOut
(iii) and the NULL for the NSFileHandleReadCompletionNotification for stdErr

Well when it was dropping the data I was missing one of these notifications and 
my empirical observation was that more commonly I was receiving the 
NSTaskDidTerminateNotification first and then either of the other notifications.

Whereas when things were working it was uncommon or I didn't get the 
NSTaskDidTerminateNotification first.... It was just a data point I was trying 
to give everyone so it might shed some light on the problem.


> On Mar 17, 2011, at 4:01 AM, Jason Harris wrote:
> 
>> - (BOOL) waitTillFinished
>> {
>>   // wait for task to exit:
>>   while (![self shouldFinishUp])
>>   {
>>   // If the task is terminated we should set up a pending termination 
>> which will terminate in a bit. This catches some
>>   // zombie NSTasks where either the outputData or errorData of 0 were 
>> never posted..
>>   BOOL terminated = ![task_ isRunning];
>>   if (terminated && !pendingTermination_)
>>   {
>>   DebugLog(@"...Found terminated for %@ ...", [self 
>> commandLineString]);
>>   [self setPendingTermination];
>>   }
>> 
>>   BOOL runLoopRan = [[NSRunLoop currentRunLoop] 
>> runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
>>   if (!runLoopRan)
>>   break;
>>   if (!isFinished_)
>>   DebugLog(@"...waitTillFinished still waiting for %@ ...", [self 
>> commandLineString]);
>>   }
>> 
>>   [self finishUp];
>>   DebugLog(@"...Exiting waitTillFinished for %@ ...", [self 
>> commandLineString]);
>>   return (result_ == 0);
>> }
>> 
>> 
>> + (ExecutionResult*) execute:(NSString*)cmd withArgs:(NSArray*)args 
>> onTask:(NSTask*)task
>> {
>>   ShellTask* 

Re: NSTask is intermittently failing to return results.

2011-03-19 Thread Jason Harris

On Mar 19, 2011, at 1:27 PM, Ken Thomases wrote:

> On Mar 18, 2011, at 5:32 PM, Jason Harris wrote:
> 
>> On Mar 18, 2011, at 11:07 PM, Ken Thomases wrote:
>> 
>>> The exception is saying that the file descriptor backing the 
>>> NSPipe/NSFileHandle has been closed.  Retrying after some time can only 
>>> result in the frameworks co-opting a new, unrelated file object that 
>>> happened to get the same file descriptor.  That would explain why your 
>>> reads sometimes never get any data -- you're reading from a completely 
>>> different file object.
>> 
>> I am sorry, but can you explain the paragraph in more detail?
> 
> Well, are you familiar with file descriptors?  When you open a file, pipe, 
> socket, or whatever, you get a file descriptor by which to refer to it.  A 
> file descriptor is just a number, like 5.  When you use Cocoa's NSPipe or 
> NSFileHandle, these details are hidden behind the scenes.
> 
> Anyway, something may be closing the file descriptor.  When that happens, 
> _for a while_ any code which tries to use that file descriptor (in this case, 
> 5) with the system calls for reading from the file will get an error, EBADF, 
> indicating that the file descriptor doesn't refer to an open file.  However, 
> and this is very important, it is very likely that future requests to open 
> files, pipes, sockets, etc. will reuse the file descriptor.  That is, some 
> other part of the code will open a file and receive the file descriptor 5 for 
> its open file.  Once that happens, the original code which had been use file 
> descriptor 5 can't tell that this new file descriptor 5 is not the one it 
> used to own.  It will keep trying to use it, and that may seem to succeed, 
> but it's accessing a completely different file than it should be.  It may be 
> trying to read from a file which will never receive any data, which would 
> explain why you don't receive the output from your task.

I was sort of aware of this but its very nice to have it explained in the 
context of my problem. Thank you!


>> (Just to be clear sometimes I never get the exception and yet it still drops 
>> data... So the ugly bit of the @catch is never hit but it still was dropping 
>> the data...)
> 
> Note that there's no guarantee that your attempt to read from the file 
> descriptor will happen during the window when the file descriptor is invalid. 
>  The file descriptor may be closed and then nearly-immediately reused for a 
> different file, and your first attempt to read from it will access a 
> different, unrelated file.  That would be bad and wrong, but would not cause 
> the exception resulting from an EBADF error.
> 
> 
>>> I'm not sure why the file descriptor is being closed.  It may be a 
>>> framework bug having to do with garbage collection.
>>> 
>>> I'd try creating the file descriptors manually with the pipe(2) system 
>>> call.  Then, construct NSFileHandles from them with 
>>> -initWithFileDescriptor:theReadFD closeOnDealloc:NO.
>> 
>> Sorry just so I don't stuff this up can I ask you to give me the exact code 
>> here... or point me to an example of this?
> 
> Well, this is sketched in mail.  By the way, I reviewed the docs and the 
> closeOnDealloc:NO part is not necessary since that's the default:
> 
>   int out_pipe_fds[2];
>   // Creates a pipe consisting of two file descriptors.  The [0] element 
> gets the read end of the
>   // pipe; the [1] element gets the write end.
>   if (pipe(out_pipe_fds) != 0)
>   /* handle error */;
>   NSFileHandle* outReadHandle = [[NSFileHandle alloc] 
> initWithFileDescriptor:out_pipe_fds[0]];
>   NSFileHandle* outWriteHandle = [[NSFileHandle alloc] 
> initWithFileDescriptor:out_pipe_fds[1]];
>   [task setStandardOutput:outWriteHandle];
> 
>   // Initiate reading on the read handle, including observing the 
> appropriate notification
> 
>   // Repeat for stderr
> 
>   [task launch];
>   [outWriteHandle release];
>   close(out_pipe_fds[1]);
>   // Repeat for stderr
> 
>   // ...
> 
>   // After you've received the end-of-file indication:
>   [outReadHandle release];
>   close(out_pipe_fds[0]);

Thanks!

> 
>>> I see no evidence that it has "vanished".  It seems to me that 
>>> -waitTillFinished is still executing, presumably blocked in the run loop.  
>>> Note that, not only is the DebugLog at the end of -waitTillFinished not 
>>> hit, but neither is the one immediately after the call to it in 
>>> +execute:withArgs:onTas

Re: NSTask is intermittently failing to return results.

2011-03-19 Thread Jason Harris
Sorry I have to break this into several replies to get around the automatic 
size limits of post to this group. So here is the reply in a couple of bites:

On Mar 19, 2011, at 8:43 PM, Bill Monk wrote:

>> I have looked at (in fact studied in detail) the source code for Moriarity, 
>> AMShellWrapper, MyTask, and OpenFileKiller
> 
> I don't mean this to be as harsh, the way it will look in print but...Really? 
> Those projects show how simple it should be. You are making it complicated. 
> And weird.

Uhmmm... My code was based on those projects, and its very very similar to 
those projects. Probably most similar to OpenFileKiller and MyTask since they 
both use the run loop approach ie they wanted to synchronously call NSTask 
using the asynchronous notification mechanisms. One interesting thing I found 
about MyTask is that the exit notification is never caught in the run loop (at 
least in my experimentation) since the run loop was working in a different mode 
yet the notification was delivered in the NSDefaultRunLoopMode...) But anyway 
my code was strongly based on theirs so it really shouldn't be all that 
different or shocking to you.


>> NSTask is most of the time working for me, but intermittently it's failing 
>> to return results. Either the result is silently dropped, or more 
>> infrequently I am getting exceptions in:
>> 
>> [NSConcreteData initWithBytes:length:copy:freeWhenDone:bytesAreVM:] or
>> [NSConcreteFileHandle availableData] or
>> [NSConcreteFileHandle readDataOfLength:]
>> 
>> depending on the tweaks / experiments I am attempting to play with.
> 
> I've never seen anything like that with NSTask.

Other people have and its documented. Just google for it, or even look at the 
links I included in my original post. Likely there are / were making the same 
small subtle mistakes that I am / was.


> I do not find it flaky or intermittent. But when I run your app, following 
> your instructions, I don't get crashes, I just get an ever-increasing number 
> of unfinished tasks (with indeterminate progress indicators) in the 
> Information pane at lower left. Looks like just another manifestation of the 
> same problem.

Were you breaking on exceptions? Also it didn't crash since the exceptions were 
caught... Also if you are building from source then the tip revision as of now 
is of course not a good version to actually *do things* with. It was the 
example code which I was having problems with which I posted to this list...


> Some big differences between your code and how NSTask is supposed to work are:
> 
> * What's all this polling in -waitTillFinished after calling -launch on the 
> task? Forget running your own runloop here. Why?

This is exactly what OpenFileKiller and MyTask do. How can you say those other 
projects "show how simple it should be" if you haven't even read their 
code?!?... That was their way to get synchronous reading from the asynchronous 
notifications. It seemed like the standard way to do it from what I saw 
googling around. In fact if you look at the documentation on NSTask you see:

waitUntilExit
Block until the receiver is finished.

- (void)waitUntilExit
Discussion
This method first checks to see if the receiver is still running using 
isRunning.
Then it polls the current run loop using NSDefaultRunLoopMode until the task
completes.

Ie apple is internally messing with runLoops to make this work. The other 
sample codes written by others were just making this a bit more explicit I 
guess... Or working around bugs, or something... (Note there are lots of 
questions on NSTask if you google for it...)


> Either just exit and let the notifications tell you when the task is done, or 
> you call -waitUntilExit on the task, and block right there. 

Well yes. The waitUntilExit does seem to be working.  Which was pointed out by 
Jonathan Mitchell. It appears strange to me that one can simply use this, and 
that someone as knowledgeable as Matt Gallagher was using the more complicated 
runLoop approach that I initially tried to use. Maybe the explicit runLoop 
approach solved some bugs at one time or another for him?

Note that the only piece of sample code which I have seen while googling around 
on NSTaskk that uses the [task waitUntilExit] approach is now the code Jonathan 
Mitchell pointed out to us.


> * Why are you trying to *infer* when the task is done? You've got the ivars 
> isFinished_ and pendingTermination_, and methods -shouldFinishUp, -finishUp  
> and -waitTillFinished (that runs the unnecessary runloop), a 
> -setPendingTermination to call -finishUp after a 10 second delay after you 
> guess that the task might be finished, and a -resetPendingTermination method 
> to try again if the previous guess was wrong.
> 
> This is madness - this is all unnecessary. You've got a crash, and you have 
> to find and fix it. Adding all these layers just masks the problem, and makes 
> it harder to find. None of the sample code you referenced go through any of 

Re: NSTask is intermittently failing to return results.

2011-03-19 Thread Jason Harris
Answer part II

On Mar 19, 2011, at 8:43 PM, Bill Monk wrote:


> Please, you must stop now, you're going to make yourself nuts. :)
> 
> - (void) gotError:(NSNotification*)notification
> {
> 
> (@"...got NULL Error Output for %@ ...", [self commandLineString]);
> errHandle_ = nil;
> if ([self shouldFinishUp])
> [self finishUp];
> 
> Why do you care if the error output is null? Getting a single zero-length 
> NSData from the stdErr pipe is normal if the task completed without error. 
> Why? Because when you call readInBackgroundAndNotify, it calls availableData 
> on the file handle. Docs say availableData "Returns an empty data object if 
> the end of file is reached", so you might get a notification with a 
> zero-length NSData. That is not an indication that the task is finished, or 
> that you should set its stdErr filehandle to nil, or that you should start 
> guessing whether the task it done. It will notify you when it is done.
> 
> When you receive your gotError method, just do whatever you want to do with 
> the actual error data. Thats's all. If there's not any data, fine. That does 
> not indicate an error. 
> 
> 
> * When you receive NSTaskDidTerminateNotification, simply believe it. Close 
> up shop. If you want the tasks's status, call terminationStatus. But don't 
> try to guess if it's "really" finished, or "really and truly finished", or 
> "really, truly, for sure, for certain, finished". It is finished. 

Uhh no... you are *quite* wrong in that last paragraph. Again look at Moriarty, 
AMShell, OpenFileKiller, and MyTask. In fact others in this very thread 
commented on this. Reread some of the others comments about this. The exit 
notification is *not* enough to exit. It just means that the task finished, it 
doesn't mean that you have got all the output and or errors yet. You are 
receiving them asynchronously, and they could, and very often are, out of order.

Please see the other sample codes for examples...


> What you've got here, no:
> 
> - (void) gotExit:(NSNotification*)notification
> {
>   if (notification)
>   DebugLog(@"...got Exit for %@ ...", [self commandLineString]);
>   if ([self shouldFinishUp])
>   [self finishUp];
> else
> [self setPendingTermination];
> }
> 
> If something is happening that makes you think it's not REALLY finished, find 
> and fix THAT bug. All this method needs to do is 
> 
> Also, why is this doing this?
> 
> if (notification)
> 
> The method wouldn't be called if there weren't a notification. And all it 
> needs to do is call your finishUp method.

That was in there since eg MyTask calls the finishing method both as a 
notification and as a way to finish things up. At one stage I did the same. I 
have been through lots of variants in order to find the right way to do things.


Cheers,
  Jas___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: NSTask is intermittently failing to return results.

2011-03-19 Thread Jason Harris
Answer part III

On Mar 19, 2011, at 8:43 PM, Bill Monk wrote:

> * Except, when it finally does call finishUp (if it ever does; here it seems 
> to get into an infinite loop), it's just too complicated. All you do here is 
> unregister observers, read any remaining data, and dispose of file handles 
> etc. 
> 
> Some comment on -finishUp are below.
> 
> 
> - (void) finishUp
> {
>   if (isFinished_) 
>   return;
>   
>   DebugLog(@"...Finishing up for %@ ...", [self commandLineString]);
>   
>   [NSObject cancelPreviousPerformRequestsWithTarget:self  
> selector:@selector(finishUp)  object:nil];
>   [self stopObserving:NSFileHandleReadCompletionNotification from:nil];
>   [self stopObserving:NSTaskDidTerminateNotification from:nil];
>   
>   [task_ terminate];
>   
>   // Clear standard out and standard error
>   NSData* data;
>   while ((data = [outHandle_ availableDataIgnoringErrors]) && [data 
> length])
>   [outputData_ appendData:data];  
>   while ((data = [errHandle_ availableDataIgnoringErrors]) && [data 
> length])
>   [errorData_ appendData:data];
>   
>   outHandle_ = nil;
>   errHandle_ = nil;
>   result_ = [task_ terminationStatus];
>   isFinished_ = YES;  
> }
> 
> 
> ---
>   if (isFinished_) 
>   return;
> 
> You don't need to check (or maintain) an isFinished ivar - the task is 
> finished. It just told you so.

isFinished was recording if the finalizer had been called.

Ie if the run loop had been working and the exit notification fired and was 
correctly caught and control returned to the runloop like I had intended then 
reading the code its pretty clear that finishUp could be called more than once. 
When things fire asynchronously you sometimes need to have guards. This 
condition was such a guard.


> ---
>   cancelPreviousPerformRequestsWithTarget 
> 
> Lose all this stuff - it only serves to hide problems.You think it's helping 
> and then the code gets on a different machine and instead of crashing, it 
> does other weird stuff that never happened on your machine, like the 
> never-ending tasks I'm seeing here. 

Again, other people had this...


> 
>   [task_ terminate];  
> 
> Why? This accomplishes nothing - the task has terminated. If you -did- need 
> to terminate it, say because the app is quitting, you'd do that elsewhere, 
> not in the method that gets called in response to a task termination.
> 

Apples Moriarty sample had this code. (Amongst other projects out there.)


> 
>   while ((data = [outHandle_ availableDataIgnoringErrors]) && [data 
> length])
>   [outputData_ appendData:data];  
>   while ((data = [errHandle_ availableDataIgnoringErrors]) && [data 
> length])
>   [errorData_ appendData:data];
> 
> 
> If it were my code, I would remove this wholly bogus 
> availableDataIgnoringErrors method. At best, it's a band-aid covering up 
> serious problems.

AMTask had this block of code without the error handling. Others do it as well 
when I googled around... As far as the error handling, again I very much wanted 
to remove this handling and solve the main problem... hence... *I posted to 
this news group* in order to find a way not to use this exception handling, and 
basically fix the problems I was having. 


> Also, it is NOT ignoring "errors", it ignores NSFileHandleOperationException, 
> which should not be happening. (And, a -regex- in the @catch block to check 
> [error reason]??? Simplify...)
> 
> Docs say: "Raised by NSFileHandle if attempts to determine file-handle type 
> fail or if attempts to read from a file or channel fail." 
> 
> That exception is valuable info that your code has, somewhere, hosed things 
> up. Stop trying to suppress useful crashes - embrace them and fix their 
> causes.

U... Thats the exact reason why I was posting here...

In summary please read the code in eg Moriarty, AMTask, OpenFileKiller, or 
MYTask code in order to follow up...

And again. I wasn't saying the code was perfect... In fact far from it. Hence 
my posting and request for help to this list...  I was trying to use basically 
the other code out there that I had seen. In addition since I was having 
problems and couldn't find the solution I was trying the next best thing of 
course of trying to at least catch the errors. (Nowhere near as good as solving 
the original problem which I really very badly wanted to fix.)

Happily with Jonathan pointing out apples sample code of 
CommandLineToolPlugin.m, my code here is now much much simpler:

Cheers,
  Jas___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa

GCD dispatch workers and termination

2011-03-27 Thread Jason Harris
Hi All,

Following on from some of the issues I had and people raised about NSTasks 
intermittently failing I now have the following issue. When I profile my 
application (MacHg) in threads, I can see a large number of DispatchWrokers 
which are created but never seem to exit. In an effort to track down whats 
going on I can create a very small project and see the exact same behavior.

To replicate this in a dummy app one can go and create a new XCode document 
based cocoa application, and add the following method:

- (void) doWorkerLaunches
{
for (int i = 1; i <50; i++)
{
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSTask* task = [[NSTask alloc] init];
[task setLaunchPath: @"/bin/ls"];

NSArray* arguments = [NSArray arrayWithObjects: @"-l", @"-a", 
@"-t", nil];
[task setArguments: arguments];

NSPipe* pipe = [NSPipe pipe];
[task setStandardOutput: pipe];

NSFileHandle* file = [pipe fileHandleForReading];

[task launch];
[task waitUntilExit];

NSData* data = [file readDataToEndOfFile];
});
}
}

Then I change windowControllerDidLoadNib like so:

- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
[super windowControllerDidLoadNib:aController];
[self performSelector:@selector(doWorkerLaunches) withObject:nil 
afterDelay:2.0];
}

So basically 2 seconds after launch I go do a lot of parallel dispatched tasks 
of launching ls.

I turn on garbage collection in the project. (This doesn't seem to make any 
difference one way or the other.) Then I build the project. Then run this 
project in instruments with the "Threads instrument" and I get lots of 
DispatchWorkers that didn't terminate.

The screen shot of the non-terminated DispatchWorkers is here: 
http://jasonfharris.com/files/misc_snippets/threadsDispatchWorkers.png
I have zipped this simple project up and put it here: 
http://jasonfharris.com/files/misc_snippets/gcdGroups.zip

Can anyone shed some light on why these DispatchWorkers are not terminating?

Thanks!
   Jason___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: GCD dispatch workers and termination

2011-03-27 Thread Jason Harris

On Mar 27, 2011, at 10:56 PM, Kyle Sluder wrote:

> On Sun, Mar 27, 2011 at 11:27 AM, Jason Harris  wrote:
>> Can anyone shed some light on why these DispatchWorkers are not terminating?
> 
> Are they doing any work? If not, why does it matter? GCD might be
> keeping them around, anticipating more I/O-bound work. It is a thread
> pool API, after all.

Hmmm... It's possible... I noticed that when I don't actually use an NSTask and 
do some printf(stderr,...) or something like that then the DispatchWorkers do 
actually terminate.

Also if I change from:

[self performSelector:@selector(doWorkerLaunches) withObject:nil 
afterDelay:2.0];

to:

[self performSelector:@selector(doWorkerLaunches) withObject:nil 
afterDelay:2.0];
[self performSelector:@selector(doWorkerLaunches) withObject:nil 
afterDelay:10.0];
[self performSelector:@selector(doWorkerLaunches) withObject:nil 
afterDelay:20.0];

And look at this in instruments it looks like each time the doWorkerLaunches 
fires it starts a whole bunch of new workers and threads, ie it appears that 
none of these threads where the DispatchWorker was not terminated are being 
reused (I would think the DispatchWorker would have to terminate in order to 
reuse the thread right? But I am guessing here...)

(This sort of models the situation in my real application. Ie nothing... 
nothing... then a flood of say 15 dispatches, then nothing... nothing... 
nothing... another flood... etc.)

Thus it feels to me as if this is really leaking resources... since each thread 
has an overhead and looks like it is not being terminated and the number of 
threads is just growing...

Cheers,
  Jas___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: GCD dispatch workers and termination

2011-03-27 Thread Jason Harris

On Mar 27, 2011, at 11:14 PM, Ken Thomases wrote:

> On Mar 27, 2011, at 1:27 PM, Jason Harris wrote:
> 
>> - (void) doWorkerLaunches
>> {
>>   for (int i = 1; i <50; i++)
>>   {
>>   dispatch_async(dispatch_get_global_queue(0,0), ^{
>>   NSTask* task = [[NSTask alloc] init];
>>   [task setLaunchPath: @"/bin/ls"];
>> 
>>   NSArray* arguments = [NSArray arrayWithObjects: @"-l", @"-a", 
>> @"-t", nil];
>>   [task setArguments: arguments];
>> 
>>   NSPipe* pipe = [NSPipe pipe];
>>   [task setStandardOutput: pipe];
>> 
>>   NSFileHandle* file = [pipe fileHandleForReading];
>> 
>>   [task launch];
>>   [task waitUntilExit];
>> 
>>   NSData* data = [file readDataToEndOfFile];
>>   });
>>   }
>> }
> 
> Possibly unrelated to your issue with the dispatch threads (although possibly 
> related), the above use of NSTask is somewhat broken.  You've made a common 
> mistake.  It is not OK to block waiting for the task to exit when you haven't 
> established an ongoing asynchronous read of its output (when you're capturing 
> the output rather than letting it go to file, /dev/console, or /dev/null, 
> etc.).
> 
> The problem is that pipes have a fixed buffer in the kernel.  If a task 
> writes more than that amount to the pipe when no reader is draining the pipe, 
> the writer blocks.  You don't read from the pipe until after the task has 
> exited, but the task may be prevented from exiting because you're not reading 
> from the pipe.  Classic deadlock.
> 
> Put another way, have you confirmed that your tasks are really completing?  
> Maybe the dispatch threads are still alive because of this deadlock I'm 
> describing.  (I guess it depends on whether your "ls -l -a -t" command is 
> producing more output than the size of a pipe's buffer, which in turn depends 
> on the current working directory and its contents.)

Thanks! Just to try this out I'll rework into the notification form of NSTask 
and then retest... More soon...

Thanks,
   Jas___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: GCD dispatch workers and termination

2011-03-27 Thread Jason Harris
> Possibly unrelated to your issue with the dispatch threads (although possibly 
> related), the above use of NSTask is somewhat broken.  You've made a common 
> mistake.  It is not OK to block waiting for the task to exit when you haven't 
> established an ongoing asynchronous read of its output (when you're capturing 
> the output rather than letting it go to file, /dev/console, or /dev/null, 
> etc.).
> 
> The problem is that pipes have a fixed buffer in the kernel.  If a task 
> writes more than that amount to the pipe when no reader is draining the pipe, 
> the writer blocks.  You don't read from the pipe until after the task has 
> exited, but the task may be prevented from exiting because you're not reading 
> from the pipe.  Classic deadlock.
> 
> Put another way, have you confirmed that your tasks are really completing?  
> Maybe the dispatch threads are still alive because of this deadlock I'm 
> describing.  (I guess it depends on whether your "ls -l -a -t" command is 
> producing more output than the size of a pipe's buffer, which in turn depends 
> on the current working directory and its contents.)

Thanks again Ken for you suggestion on this bug and on the last one to do with 
NSTask.

Right, I have changed the example a bit so that the NSTask in this case is 
using notifications. I also get it to print the output. Actually now I can see 
this is reproducing the old problem I had of some of the output results being 
just simply dropped.

Eg Here is the new code (header):

@interface ShellTask : NSObject
{
NSString*   generatingCmd_; // The command that was 
executed
NSArray*generatingArgs_;// The arguments used 
to the command
int result_;// The 
result of executing the command
NSTask* task_;  // The NSTask 
we are trying to perform
NSFileHandle*   outHandle_;
NSFileHandle*   errHandle_;
NSMutableData*  outputData_;
NSMutableData*  errorData_;
}

@property (nonatomic, assign) NSTask* task;

+ (void) execute:(NSString*)cmd withArgs:(NSArray*)args;

@end


Here is the new code (body):
---


- (void) doWorkerLaunches
{
for (int i = 1; i <50; i++)
{
dispatch_async(dispatch_get_global_queue(0,0), ^{
[ShellTask execute:@"/bin/ls" withArgs:[NSArray 
arrayWithObjects: @"-l", @"-a", @"-t", nil]];
});
}   
}



@implementation ShellTask

@synthesize task = task_;

- (void) gotOutput:(NSNotification*)notification
{
NSData* data = [notification.userInfo 
objectForKey:NSFileHandleNotificationDataItem];
if (notification.object == outHandle_)
{
if (data.length > 0)
{
[outputData_ appendData:data];
[outHandle_ readInBackgroundAndNotify];
}
else
outHandle_ = nil;
}
}

- (void) gotError:(NSNotification*)notification
{
if (notification.object == errHandle_)
{
NSData* data = [notification.userInfo 
objectForKey:NSFileHandleNotificationDataItem];
if (data.length > 0)
{
[errorData_ appendData:data];
[errHandle_ readInBackgroundAndNotify];
}
else
errHandle_ = nil;
}
}

- (BOOL) waitTillFinished
{
[task_ waitUntilExit];  
[[NSNotificationCenter defaultCenter] removeObserver:self 
name:NSFileHandleReadCompletionNotification object:nil];

[task_ terminate];
result_ = [task_ terminationStatus];
outHandle_ = nil;
errHandle_ = nil;

return (result_ == 0);
}


- (id) initWithCommand:(NSString*)cmd andArgs:(NSArray*)args
{   
generatingCmd_ = cmd;
generatingArgs_ = args;
task_ = [[NSTask alloc] init];  

NSPipe* outPipe= [[NSPipe alloc] init]; // Create the pipe to 
write standard out to
NSPipe* errPipe= [[NSPipe alloc] init]; // Create the pipe to 
write standard error to
outHandle_  = [outPipe fileHandleForReading];
errHandle_  = [errPipe fileHandleForReading];
outputData_ = [[NSMutableData alloc] init];
errorData_  = [[NSMutableData alloc] init];

[task_ setLaunchPath:cmd];
[task_ setArguments:args];
[task_ setStandardInput:[NSPipe pipe]];
[task_ setStandardOutput:outPipe];
[task_ setStandardError:errPipe];

[[NSNotificationCenter defaultCenter] addObserver:self 
selector:@selector(gotOutput:) name:NSFileHandleReadCompletionNotification 
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self 
selector:@selector(gotError:)  name:NSFileHandleReadCompletionNotification 
object:nil];

[outHandle_ readInBackgroundAndNotify];
[errHandl

Re: GCD dispatch workers and termination

2011-03-27 Thread Jason Harris
> Possibly unrelated to your issue with the dispatch threads (although possibly 
> related), the above use of NSTask is somewhat broken.  You've made a common 
> mistake.  It is not OK to block waiting for the task to exit when you haven't 
> established an ongoing asynchronous read of its output (when you're capturing 
> the output rather than letting it go to file, /dev/console, or /dev/null, 
> etc.).
> 
> The problem is that pipes have a fixed buffer in the kernel.  If a task 
> writes more than that amount to the pipe when no reader is draining the pipe, 
> the writer blocks.  You don't read from the pipe until after the task has 
> exited, but the task may be prevented from exiting because you're not reading 
> from the pipe.  Classic deadlock.
> 
> Put another way, have you confirmed that your tasks are really completing?  
> Maybe the dispatch threads are still alive because of this deadlock I'm 
> describing.  (I guess it depends on whether your "ls -l -a -t" command is 
> producing more output than the size of a pipe's buffer, which in turn depends 
> on the current working directory and its contents.)

BTW, I tried your suggested approach of manually creating the pipe's. The full 
code I used for that trial is at:
http://jasonfharris.com/files/misc_snippets/gcdGroupsNotificationsManualPipes.zip

Basically the two main changes are:

- (id) initWithCommand:(NSString*)cmd andArgs:(NSArray*)args
{   
generatingCmd_ = cmd;
generatingArgs_ = args;
task_ = [[NSTask alloc] init];  

int createStdOutPipe = pipe(stdoutPipe_fds);
int createStdErrPipe = pipe(stderrPipe_fds);
if (createStdOutPipe != 0)
fprintf(stderr, "couldn't create pipe\n");
if (createStdErrPipe != 0)
fprintf(stderr, "couldn't create pipe\n");

outReadHandle_  = [[NSFileHandle alloc] 
initWithFileDescriptor:stdoutPipe_fds[0]];
outWriteHandle_ = [[NSFileHandle alloc] 
initWithFileDescriptor:stdoutPipe_fds[1]];
errReadHandle_  = [[NSFileHandle alloc] 
initWithFileDescriptor:stderrPipe_fds[0]];
errWriteHandle_ = [[NSFileHandle alloc] 
initWithFileDescriptor:stderrPipe_fds[1]];
[task_ setStandardOutput:outWriteHandle_];
[task_ setStandardError:errWriteHandle_];
outputData_ = [[NSMutableData alloc] init];
errorData_  = [[NSMutableData alloc] init];

[task_ setLaunchPath:cmd];
[task_ setArguments:args];
[task_ setStandardInput:[NSPipe pipe]];

[[NSNotificationCenter defaultCenter] addObserver:self 
selector:@selector(gotOutput:) name:NSFileHandleReadCompletionNotification 
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self 
selector:@selector(gotError:)  name:NSFileHandleReadCompletionNotification 
object:nil];

[outReadHandle_ readInBackgroundAndNotify];
[errReadHandle_ readInBackgroundAndNotify];

return self;
}


+ (void) execute:(NSString*)cmd withArgs:(NSArray*)args
{
ShellTask* shellTask = [[ShellTask alloc] initWithCommand:cmd 
andArgs:args];

[shellTask->task_ launch];  // Start the process
[shellTask->outWriteHandle_ release];
[shellTask->errWriteHandle_ release];
close(shellTask->stdoutPipe_fds[1]);
close(shellTask->stderrPipe_fds[1]);

[shellTask waitTillFinished];
[shellTask->outReadHandle_ release];
[shellTask->errReadHandle_ release];
close(shellTask->stdoutPipe_fds[0]);
close(shellTask->stderrPipe_fds[0]);

NSString* outStr = [[NSString alloc] 
initWithData:shellTask->outputData_ encoding:NSUTF8StringEncoding];
NSString* errStr = [[NSString alloc] initWithData:shellTask->errorData_ 
 encoding:NSUTF8StringEncoding];
fprintf(stderr, "output:\n%s\n", [outStr UTF8String]);
if ([errStr length] > 0)
fprintf(stderr, "error:\n%s\n", [errStr UTF8String]);
}

-

Unfortunately this still seems to have the same behavior as before, but I might 
have done something wrong here... Its still "skipping" doing various tasks. If 
I put in a delay on the launch of each task of around .2 seconds then many 
fewer tasks are "skipped" but still clearly it appears something is going on.

Have I set up the NSTasks wrong? Or is the lower level code failing when it is 
getting simultaneous task requests?

Cheers & Thanks,
   Jas

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Automatic graphics switching...

2011-03-29 Thread Jason Harris
Hi All,

Some users are complaining that my application (MacHg) is causing their 
MacBooks to switch from using the integrated Intel (lower power) card to the 
NVIDIA (higher power) graphics card. 

Eg some related articles I dug up:
http://appletoolbox.com/2010/05/macbook-pro-mid-2010-graphics-switching-which-apps-trigger-how-to-monitor/
http://www.cocoabuilder.com/archive/cocoa/293116-i5-i7-auto-graphics-switching.html
http://support.apple.com/kb/HT3207

However, my application doesn't appear on the surface to make heavy use of 
graphics. (It does make heavy use of GCD though).  Is there a general cause for 
this switching of the graphics card?.  How can I find out when such a switch 
occurs in my code and for what reasons?  Is there some technical article which 
explains the details of what's going on here?

Thanks!
   Jas___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Automatic graphics switching...

2011-03-29 Thread Jason Harris

On Mar 29, 2011, at 11:36 PM, Nick Zitzmann wrote:

> 
> On Mar 29, 2011, at 3:16 PM, Jason Harris wrote:
> 
>> Hi All,
>> 
>> Some users are complaining that my application (MacHg) is causing their 
>> MacBooks to switch from using the integrated Intel (lower power) card to the 
>> NVIDIA (higher power) graphics card. 
>> 
>> Eg some related articles I dug up:
>> http://appletoolbox.com/2010/05/macbook-pro-mid-2010-graphics-switching-which-apps-trigger-how-to-monitor/
>> http://www.cocoabuilder.com/archive/cocoa/293116-i5-i7-auto-graphics-switching.html
>> http://support.apple.com/kb/HT3207
>> 
>> However, my application doesn't appear on the surface to make heavy use of 
>> graphics. (It does make heavy use of GCD though).  Is there a general cause 
>> for this switching of the graphics card?.  
> 
> There are a few of them I know about:
> 1. Your application starts CoreAnimation by calling -setWantsLayer: on a view 
> with a layer, or adding a layer in IB

Ahhh... yes I use core animation, but just very very lightly... some simple 
static stuff like:

CIColor* black   = [CIColor colorWithRed:  0.0/255.0 green:  0.0/255.0 
blue:  0.0/255.0 alpha:1.0];
CIColor* color0  = [CIColor colorWithRed: 77.0/255.0 green: 78.0/255.0 
blue: 87.0/255.0 alpha:0.8];
CIColor* color1  = [CIColor colorWithRed: 39.0/255.0 green: 40.0/255.0 
blue: 52.0/255.0 alpha:0.5];
CIVector* center = [self recomputePosition];
NSNumber* radius = radius_ ? radius_ : [NSNumber numberWithFloat:450.0];

CIFilter* gradiantFilter = [CIFilter 
filterWithName:@"CIGaussianGradient"];
[gradiantFilter setValue:color0 forKey:@"inputColor0"];
[gradiantFilter setValue:color1 forKey:@"inputColor1"];
[gradiantFilter setValue:center forKey:@"inputCenter"];
[gradiantFilter setValue:radius forKey:@"inputRadius"];

CIFilter* constantFilter = [CIFilter 
filterWithName:@"CIConstantColorGenerator"];
[constantFilter setValue:black forKey:@"inputColor"];

foregroundFilters_ = [NSArray arrayWithObject:gradiantFilter];
backgroundFilters_ = [NSArray arrayWithObject:constantFilter];

[[self layer] setFilters: foregroundFilters_];
[[self layer] setBackgroundFilters:backgroundFilters_];

Not much more... Ohh well at least I know where its coming from then!

Thanks!
   Jas

> 2. Your application initializes an NSOpenGLView using a pixel format that 
> works best using the discrete GPU
> 3. Your application initializes a QTCaptureView, QTMovieView, or QCView
> 4. The user plugged in an external display (external displays must use the 
> discrete GPU)
> 
> There might be more, but those are the ones I know about.
> 
>> How can I find out when such a switch occurs in my code and for what 
>> reasons?  
> 
> If you have a dual-GPU Mac, then try breaking on IOServiceOpen and look at 
> the stack trace when it breaks. If you don't, then you can't.
> 
> Nick Zitzmann
> <http://www.chronosnet.com/>
> 

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


An "Open With..." submenu...

2011-04-02 Thread Jason Harris
Hi All,

Two related questions.

(1) Managing the default application for documents from a "file manager" type 
of appication.
(2) An "Open With..." menu.

---

(1) (Background: MacHg is a "browser" or "file manager" type of application 
(its a GUI for the DVCS mercurial) so its role is to manage files and sometimes 
if the user wants then open these files in the appropriate application.) Its 
quite likely that developers will want to open these documents in an 
application which is not the default. Eg if they are working with .html files 
from within MacHg they will likely be "developing" with / on them and so will 
want these files to open in bbedit, or coda, or DreamWeaver etc, rather than 
Safari, Firefox, or Chrome.

So what is the best way to manage this mapping in MacHg? Have some sort of 
table in the preferences which does this mapping from extensions to 
applications? I don't want to reinvent wheels so if there is already some code 
with is publicly viewable that does this sort of thing I would interested in 
references so I could look it over...

2.
Some users have asked for an "open with" menu to be added to MacHg. I have a 
menu delegate that captures when the contextual menu is firing and I can insert 
a "Open With..." menu at the right place and time in my 'menuNeedsUpdate' call. 
My question is does anyone have any prototype code already written that nicely 
constructs and manages the creation of this "Open With..." menu.

I would of course imagine that the results would be generated from 
LSCopyApplicationURLsForURL, but for me LSCopyApplicationURLsForURL with 
kLSRolesEditor for a file /Users/jason/Documents/myfile.txt file returns the 
following list:

(
file://localhost/Developer/Applications/Xcode.app/,
file://localhost/Applications/Microsoft%20Office%202008/Microsoft%20Excel.app/,
file://localhost/Volumes/QuickSilver/Applications%20local/Write/BBEdit.app/,
file://localhost/Volumes/QuickSilver/Applications/TextEdit.app/,
file://localhost/Applications/TextWrangler.app/,
file://localhost/Volumes/QuickSilver/Developer/Applications/Dashcode.app/,
file://localhost/Volumes/TSL/Applications/TextEdit.app/,
file://localhost/Volumes/QuickSilver/Applications%20local/Write/Word%20Processing/Nisus%20Writer%20Express.app/,
file://localhost/Applications%20local/Utilities/File/HexEdit/HexEdit.app/,
file://localhost/Applications/Microsoft%20Office%202008/Microsoft%20Word.app/,
file://localhost/Developer/Applications/AD%20Viewer.app/,
file://localhost/Volumes/TSL/Applications/TextEdit.app/,
file://localhost/Developer/Applications/Dashcode.app/,
file://localhost/Volumes/QuickSilver/Applications%20local/Graphics/Adobe%20Dreamweaver%20CS4/Adobe%20Dreamweaver%20CS4.app/,
file://localhost/Volumes/QuickSilver/Applications%20local/Graphics/Adobe%20Illustrator%20CS4/Adobe%20Illustrator.app/,
file://localhost/Applications%20local/Write/BBEdit.app/,
file://localhost/Applications/TextEdit.app/,
file://localhost/Applications%20local/Graphics/Coda.app/,
file://localhost/Applications%20local/Utilities/iPhone/Stanza.app/
)

Which of course needs a bit of cleanup. Ie remove duplicate applications and 
choose those on the main drive first. If this list is empty or "too" small then 
the application should fall back on kLSRolesViewer.  Ordering preference should 
likely be given to the applications that are currently open. If its easy and 
possible then maybe ordering in the menu should be given by the last time an 
application was run? Then I can imagine if the user actually choose a 
particular application for opening the given file /document then maybe MacHg 
should order that application preferentially in the future higher in the list?  
It should definitely be the first choice in the list for the same file in the 
future. I can imagine other complications / subtleties around this topic. Thus, 
is there some source code somewhere that someone could point out with the 
recommended best practices in this sort of case?

Thanks in advance!
  Jason___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Mac App Store requirements

2011-04-10 Thread Jason Harris
Is it about as easy / difficult as adding say Sparkle support to your app? 
Easier? More difficult? (I also don't know this and I have been planning to add 
MacHg to the MacApp store at some stage in the not too distant future...)

Thanks!
  Jas

On Apr 10, 2011, at 8:47 PM, Laurent Daudelin wrote:

> There is a set of guidelines about things you should avoid if you don't want 
> your app to be rejected. Not sure if it's available to non-registered Mac 
> developers but I think it should.
> 
> -Laurent.
> -- 
> Laurent Daudelin
> AIM/iChat/Skype:LaurentDaudelin   
> http://www.nemesys-soft.com/
> Logiciels Nemesys Software
> laur...@nemesys-soft.com
> 
> On Apr 10, 2011, at 11:16, Artemiy Pavlov wrote:
> 
>> Hey all,
>> 
>> I am not yet a member of the Mac Developer program, but I am experimenting 
>> with my own Cocoa OS X app and I would like to know what are the 
>> requirements on getting it into the Mac App Store.
>> 
>> I mean, I have a 32/64 bit Intel build of a vanilla Cocoa app in XCode. 
>> Where will I go from there? Apart from signing the code with a certificate 
>> that you receive from Apple, what one needs to do to get his app bundle into 
>> the Mac App Store? 
> 
> ___
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/jason%40jasonfharris.com
> 
> This email sent to ja...@jasonfharris.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Lockless thread-safe accessor using blocks: how to?

2011-04-14 Thread Jason Harris

On Apr 14, 2011, at 7:44 PM, David Duncan wrote:

> On Apr 14, 2011, at 10:26 AM, WT wrote:
> 
>> On Apr 14, 2011, at 2:09 PM, David Duncan wrote:
>> 
>>> On Apr 14, 2011, at 10:02 AM, WT wrote:
>>> 
 I looked at dispatch_once() at one point, but I'm still confused by how it 
 works.
>>> 
>>> dispatch_once uses a predicate (just a flag) to determine if it should run 
>>> the block or not. If that flag is false, then it sets the flag to true and 
>>> executes the block. If the flag is true, it does nothing. What makes 
>>> dispatch_once useful over a simple if statement is that it ensures that if 
>>> you execute dispatch_once concurrently from multiple threads that flag gets 
>>> updated exactly once, and the block gets called exactly once.
>> 
>> Thanks for explaining it, David. The bit that was throwing me off is the 
>> predicate part. I understand now that all I need is to declare a static 
>> variable of the appropriate type and pass a pointer to it to dispatch_once().
> 
> The lifetime of the predicate needs to match that of the initialization done 
> by the block. If the block's initialization is done for an instance variable, 
> then the predicate should also be an instance variable. If the initialization 
> is for a global, the predicate should also be a global.

So I just want to confirm this... Are you saying that one can do something like:

@interface MyObject
{
dispatch_once_t initilizeComputedResource;
ComputedResource* theResource;
}

- (ComputedResource*) resource;
@end

@implementation MyObject
- (ComputedResource*) resource
{
dispatch_once(&initilizeComputedResource, ^{
theResource = [self doSomeBigComputation];
});
return theResource;
}
@end

and later I can call 

{
MyObject* anObject = [[MyObject alloc]init];
ComputedResource* r = [anObject resource];
[r doSomething];
}

and its legal? (I have GC switched on)

Looking at  
http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/c/func/dispatch_once
and the bit where it says:

 "The predicate must point to a variable stored in global or static scope. The 
result of using a predicate with automatic or dynamic storage is undefined."

Seemed to me to indicate that it wasn't valid to have the kind of code I have 
above... I would like to use the code I have above so I can ensure something is 
run *once* for a given object. (Otherwise of course I just fall back on 
@synchronized but thats longer and not as fast...)

Thanks,
  Jason

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


libraries for flashing a message

2011-05-01 Thread Jason Harris
Hi All,

Before I roll my own, I am wondering if there are any libraries around which 
can briefly display a nice notification bubble over a window. It would be 
displayed and then after say time period eg 3 seconds taken down... Any user 
initiated action that targets the responder chain for the window would also 
take down the notification, etc.

Eg have people seen the undo / redo notifications in eg pixelmator (In fact if 
the pixelmator people want to open source that fragment of their code that 
would be great!)? Or maybe some sort of growl like notification over the main 
window, which is flashed.

In my case I want to flash a message "revision not found"

Thanks for any suggestions,
   Jas___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Wolfram Research is seeking iOS / Cocoa / Mac developers

2013-06-24 Thread Jason Harris
Hi All,

Wolfram research is looking for 2 or 3 full time Cocoa / iOS / Mac developers, 
preferably with C++ experience. 
You will be able to work remotely.  If you are interested please see:
   http://www.wolfram.com/company/careers/user-interface-developers.html

Yours,
   Jason Harris
   Senior Developer, Wolfram Research
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com