Closed GoogleCodeExporter closed 9 years ago
Charles,
Cortana does not like busy loops. Everything blocks until the currently
executing function finishes. This was a deliberate decision made when
developing Sleep. There is a way to fire an event though..
use fire_event to fire an event globally to all script instances. Use
fire_event_local to fire an event to the local script instance.
Use fork to create an isolated interpreter environment that doesn't block the
parent's environment. fire_event_local will communicate with the parent
Cortana instance.
Look at lines 32-40 of irc-client.cna:
https://github.com/rsmudge/cortana-scripts/blob/master/irc-client/irc-client.cna
Original comment by rsmu...@gmail.com
on 14 May 2013 at 7:49
The IRC example isn't a good one -- the IRC client isn't waiting on a result
before the next message can process, it's an asynchronous protocol. I need a
synchronous loop, where one executes after the other.
I've tried to use fire_event_local, but that's for communicating from the
script back to the parent. I need a way to get a value from the parent
($finished) and make it accessible to the child. Pass-by-reference or otherwise.
Original comment by ChopperC...@gmail.com
on 14 May 2013 at 8:50
You can't do a busy loop in Cortana like that, it will block everything else.
The sleep function blocks as well. There are better ways to do what you want,
but I don't understand this example. You're trying to run one module 10 times
and see when any of those 10 runs complete. Is that correct?
Would you like the modules to run asynchronous of eachother and keep track of
state on a per module basis, or are you looking to have them run one at a time,
in a synchronous way?
If you want synchronous, then what I'd do is create a global $console and use
cmd, cmd_set, and friends. The &cmd functions will queue on a per-console
basis. So it won't return until the previous command finishes. That's one
option. There is a 10s timeout built into the &cmd functions.
src/armitage/ConsoleQueue.java is what cmd, cmd_set, and others expose to you.
If you want asynchronous, use &spawn to isolate each set of events to their own
cortana instance. The &spawn function is the way to decompose complex Cortana
programs and state flows into something simple and manageable.
Original comment by rsmu...@gmail.com
on 14 May 2013 at 9:05
You can do pass by reference with fork, if it's *really* what you want to do
(but I don't think it is). The way to do this is:
%store['flag'] = 0;
$lock = semaphore();
fork({
sleep(10000);
acquire($lock);
%store['flag'] = 1;
release($lock);
}, \%store, \$lock);
while (1) {
acquire($lock);
if (%store['flag'] == 1) {
println("Job is done!");
}
release($lock);
}
Original comment by rsmu...@gmail.com
on 14 May 2013 at 9:09
Why would this not be what I want to do? I don't want all of the scripts to run
at once, I want them to run one after the other.
I was almost there though, the hash was the key, as it's pass-by-reference.
This is ultimately what is working for me:
global('%status');
on ready {
println("Ready.");
%status['finished'] = 0;
fork ({
local('$i');
for ($i = 0; $i < 10; $i++) {
runModule(21, "multi/gather/filezilla_client_cred");
}
quit();
}, \%status);
}
on heartbeat_1s {
println("heartbeat.");
}
sub runModule {
%status['finished'] = 0;
local('$console $module_name $session_id');
$session_id = $1;
$module_name = $2;
println("Running $module_name");
$console = console();
cmd($console, "use $module_name");
cmd_set($console, %(session => $session_id));
cmd($console, "run");
while (%status['finished'] == 0) { sleep(100); }
}
on console {
local('$temp $r');
foreach $temp (split("\n", [$3 trim])) {
#println ($temp);
if ("[*] Post module execution completed" isin $temp) {
println("Finished!");
%status['finished'] = 1;
}
} #foreach
} # on console
Original comment by ChopperC...@gmail.com
on 14 May 2013 at 9:19
Original issue reported on code.google.com by
ChopperC...@gmail.com
on 14 May 2013 at 7:40