Equivalent for shell.timeout on Mac OSX

I am looking for something like the “shell.timeout” property on Windows for MacOS.
I like to quit the shell execution after a specific time in Mode 0

Consider using a Timer and in the Action event call the Shell.Close method.

[quote=81030:@Steve Human]I am looking for something like the “shell.timeout” property on Windows for MacOS.
I like to quit the shell execution after a specific time in Mode 0[/quote]

Mode 0 freezes execution of your app until it terminates. So there is no way to stop it from within your code. A timer with shell.close in it gets frozen as well and does not execute either.

Just experimented with that together with an endless shell (infinite loop in the script). The shell freezes the whole app, even from within a thread.

The best course of action is to use mode 1 which is asynchronous and will not freeze the app. But it cannot be stopped either.

Another approach is to set the timeout at the bash level. I found this where several techniques are discussed :
http://mywiki.wooledge.org/BashFAQ/068

Sorry for not providing more detail. I thought the hint/tip was enough.

An Asynchronous Shell (Shell.Mode = 1) combined with a Timer (Timer.Mode = Timer.ModeSingle) is the suggested solution. In addition to Shell.Close in the Timer.Action event you will want Timer.Mode = Timer.ModeOff in the Shell.Completed event. Whichever one occurs first will close/stop the other. In the Shell.Completed event, check Timer.Mode. If it is equal to Timer.ModeOff then the Shell.Completed event was triggered by Shell.Close in the Timer.Action event. Otherwise the Shell completed normally and the Timer should be set to Timer.ModeOff.

Threads are not necessary because an Asynchronous Shell will not hinder the main thread. Whatever is executed in the Shell may even run on a different CPU core.

In asynchronous mode 1, Xojo shell launches the command, and lets the system manage it. It immediately returns Shell.IsRunning as False, so it is already closed.

The only way to effectively stop a mode 1 shell is to kill the process at the system level, as described in the link I provided.

Our results differ.

For a long running Shell command, Shell.IsRunning is True until the time it completes and triggers the Shell.Completed event. If Shell.Close is issued while the long running Shell command is executing, the execution of the Shell command is cancelled (confirmed via Activity Monitor), the Shell closes and the Shell.Completed event is triggered.

This is on OS X 10.9.2 with Xojo 2014 Release 1.1 and a Shell command that takes minutes to complete. I used a VMware CLI (Command Line Interface) call that clones a VM (Virtual Machine). It not only takes a while but is also disk intensive with moderate CPU and memory usage.

What did you use for your test? Perhaps different Shell commands behave differently or we are on different versions of OS X and/or Xojo.

[quote=81053:@Frederick Roller]Our results differ.

For a long running Shell command, Shell.IsRunning is True until the time it completes and triggers the Shell.Completed event. If Shell.Close is issued while the long running Shell command is executing, the execution of the Shell command is cancelled (confirmed via Activity Monitor), the Shell closes and the Shell.Completed event is triggered.

This is on OS X 10.9.2 with Xojo 2014 Release 1.1 and a Shell command that takes minutes to complete. I used a VMware CLI (Command Line Interface) call that clones a VM (Virtual Machine). It not only takes a while but is also disk intensive with moderate CPU and memory usage.

What did you use for your test? Perhaps different Shell commands behave differently or we are on different versions of OS X and/or Xojo.[/quote]

I have Mavericks 10.9.3, Xojo 2014R1.1, and use a very simple long loop shell script to make sure it does not stop right away :

[code]while [ counter < 200000 ]
do
counter = counter + 1
done

while :
do
echo “Long running loops [ hit CTRL+C to stop]”
done
[/code]

But I just checked again, and you are right. For whatever reason, I did not see it before, but shell.IsRunning works, and the bash session appears in Activity Monitor and is correctly killed by shell.close. Sorry, I was in error.

So the timer with shell.close does work fine for an asynchronous shell.

For a synchronous shell in mode 0, the link I provided offers the following command which works at the bash level, so while the app is frozen, the bash timer does what the OP wanted :

shell.execute("bash -c '(sleep 10; kill $$) & exec "+f.ShellPath+"'")

f.ShellPath is the FolderItem that points to my script infinite.sh. Can be replaced by whatever bash command. Sleep 10 means the shell will be terminated after 10 seconds.

I hope so because I am using that technique in a few of my apps. :wink:

I just realized I copied the wrong script for infinite loop. Sorry. Here is the right one :

counter=1 while : do echo -n $counter " loops [ hit CTRL+C to stop] " let counter++ sleep 1 done

You could subclass the Shell in a way that Mode 0 is emulated, but an internal Timer provides a timeout as described above.

Problem is mode 0 freezes the whole app during shell execution, so there is no way even within a subclass timer to close the shell.
However, emulating mode 0 is possible with mode 1 and 2 through shell.completed and shell.dataavailable events which replace shell.result, and they permit the sue of timer and shell.close.

Yes, that’s what I had in mind. When mode is set to 0, you’d override it to 1 and use a loop with Poll to wait for the result. You could even check the timing in the loop and skip the timer in that case. If you put YieldToNextThread into the loop, it would be thread-friendlier than the native mode 0.

The loop is a good idea. However, what I find best is the bash timer : it saves any coding on Xojo side :wink:

Wouldn’t Shell.Poll in a loop be more resource intensive than a Timer used in conjunction with Shell.DataAvailable and Shell.Completed? The latter approach only executes code when the framework triggers events which seems better than repeatedly executing Shell.Poll unnecessarily.

Again, this is to fake Mode 0.

So the idea is to be resource intensive and tie up the UI like Mode 0 normally would?

More or less, unless you can think of another way to emulate mode 0.

Kem, I am not sure it is necessary to emulate the freeze from mode 0. The combination of shell.poll and shell.DataAvailable can take care of providing results the same way mode 0 would, so for all intents and purpose there is very little difference between mode 0 and mode 1 in terms of UI.

That does seem like a good way to emulate it. Wrapping the Shell.Poll loop in #Pragma BackgroundTasks might get the emulation even closer to the real thing.

We’re talking about conditions where the CLI might lock up, right? So if I’m developer, I might call the Shell like this:

result = sh.Execute( cmd, 10 ) // Where 10 is the timeout in seconds, or something

If I write it that way, I’m expecting that the interface might be locked up for up to 10 seconds. I can’t think of a way to emulate that other than a loop int eh subclass that checks the time and repeatedly calls Poll and, for greater cooperation in a threaded environment, YieldToNextThread.

As a developer, why might I do it that way instead of using mode 1 and leaving my app responsive for those 10 seconds? I have no idea, but that’s a different conversation.