Hi Riccardo Mottola,

> Wolfgang Lux wrote:
>> I finally got around to upgrade my GNUstep tree and was able to reproduce 
>> your problem.
>> Looking at the code, then, the problem is fairly obvious: When you click the 
>> pause button for the first time, the paused flag is set to YES and once the 
>> FileExecutorObject notices that the flag is set it exits the loop in 
>> do{Move,Copy,Link,Remove,Duplicate,Trash}. This also means that the 
>> secondary thread that was started to perform the operation in the 
>> FileOpExecutor +setPorts: will terminate and the executor object will be 
>> released and probably the connection to that object is closed as well. So it 
>> looks like the executor attribute in the FileOpInfo class is no longer 
>> connected to a valid object that could resume the file operation when you 
>> click the pause button again.
> where do you think the thread is "closed"? I suppose when "endOperation" gets 
> called.
> I understand it happens in "done" and "dealloc", but that path is taken only 
> when the taks ends or stop is hit (in doCopy and doMove... why the other 
> differ I'll check later on):
> 
>  if (([files count] == 0) || stopped)
>    {
>      [self done];
>    }

This code is completely irrelevant regarding the question whether the thread 
terminates.

> if stopped or paused are set as flags, the while loop gets a break, but 
> "done" is called only on a proper quit/task completion.
> 
> Thus I understand that if "pause" is hit, the loop ends, the executor should 
> stay around.
> This makes the whole "stop" a bit quirky, but that is different.
> 
> 
> if what's your understanding of termination instead?

Okay, processing is a bit obfuscated since it involves DO calls between the 
threads. I'll try my best to explain what happens when the code is run.

The auxiliary thread is started by calling 
  [NSThread detachNewThreadSelector: @selector(setPorts:)
                           toTarget: [FileOpExecutor class]
                         withObject: ports];
in method FileOpInfo -startOperation. This means that the auxiliary thread will 
execute the FileOpExecutor +setPorts: method and finish as soon as that method 
returns.

Now turning to the +setPorts: method, it uses DO to call -registerExecutor: on 
the FileOpInfo instance on the main thread. So the code in the auxiliary thread 
now waits for the -registerExecutor: call on the main thread to finish and once 
that happens the auxiliary thread will terminate.

Next looking at the -registerExecutor: method, this uses DO again to call the 
-calculateNumFiles method on the FileExecutor instance. This call is going to 
be processed on the auxiliary thread while that thread is still waiting for the 
-registerExecutor: method to finish on the main thread. Yet, since 
-calculateNumFiles is (correctly!) declared as oneway method -registerExecutor: 
will not wait for -calculateNumFiles to terminate and just return immediately. 
So the main thread sends a reply back to the auxiliary thread which is still 
executing the -calculateNumFiles method. But once -calculateNumFiles returns, 
the DO call to -registerExecutor: on the auxiliary thread will return as well 
and hence the auxiliary thread will terminate.

So finally, we can look at -calculateNumFiles. At the end, this method calls 
-performOperation and the latter calls one of the -do... methods, e.g., 
-doMove. So if the loop in -doMove is exited, which happens once the paused 
flag is set, the -doMove method, the -performOperation method and the 
-calculateNumFiles methods all exit at once. And that means the 
-registerExecutor: can return its result and terminate the auxiliary thread.

I hope that description is clear enough.

Wolfgang



_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/gnustep-dev

Reply via email to