I have a client side function that queries tables on 3 remote servers and pulls in data for each alphanumeric character from each server.
At the end of the function a timer checks the running dictionary on each server, and if each character has ran (all dictionary values set to 1b) it should kill the timer and close the connection handle.
However I've discovered that the timer isn't being stopped and after the last character has ran (dictionary values all=1b) the cycle will try to start again, which causes the system to hang.
How can I rewrite my timer function so that it effectively closes the connection handle once the value of all running is 1b?
The last 3 lines of my function look like the following...
f:{
...do stuff here...;
if[hA"all running"; system "t 0";hclose hA;];
if[hB"all running"; system "t 0";hclose hB;];
if[hC"all running"; system "t 0";hclose hC;];
}
.z.ts:{f params}
\t 5000
hA, hB, and hC are my connecton handles.
.z.ts runs the function every 5 seconds.
params is grabbing a character from the command line, which is set when the script is started.
I'd like to stop the function from running once the value of all running is 1b.
As per #terrylynch's comment of "stopping the timer after all handles have finished processing" - I joined the if statements (that stop the timer) into a singular if statement and moved it into the .z.ts function
.z.ts:{f params;if[(hA"all running")and(hB"all running")and(hC"all running");system "t 0";hclose hA; hclose hB; hclose hC]}
which upon initial testing seems to work.
Related
I have a perl script for which I would like to write a few tests. If the perl script gets supplied a specific option, the user is allowed to paste or type out multi-line input and end their input using control-d.
These are the tests I want to write:
The script (when an interactive flag is supplied) waits for (multiple lines of) input on STDIN until the user hits control-d
[this test is already implemented - but provided for completeness] The script (when a flag is supplied that indicates a redirect/pipe) consumes all input on STDIN and does not wait for control-d
The script (when no input flag is provided [interactive or redirect]) does not wait for interactive user input
Test 1 toy example
I wrote a test for test 1 that confirms input was received (it works by the parent test script printing to the child's input handle and the child modifies and prints that input back out), but that test doesn't wait for an end of input signal (e.g. control-d) (which I don't know how to send anyway). So in other words, I can confirm it receives input, but I don't know how to confirm that it waits for the user to intentionally end the input entry. I.e. How do I know that the input consumption won't stop until the user types control-d?
Here's what I have so far for test 1. I wrote a 3rd little IO::Pipe::Consumer module to be able to send input to the child process that I'm testing and I wrote a toy example of the script that allows input on STDIN from a tty.
Here is a toy version of the script I'm testing:
>perl -e 'while(<STDIN>){print("*$_")}'
test
*test
^d
>
And here is the toy test code (that I want to improve) for the above script:
>perl -e '
use IO::Pipe::Consumer;
$obj = new IO::Pipe::Consumer;
$si = $obj->getSubroutineConsumer(
sub { while(<STDIN>) print("*$_") } }
);
print $si "test\n"
'
*test
>
I thought the parent would have to print an EOF (e.g. like what you get from "control-d") to end the input in the test, but the test ends immediately even though I'm not sending any such end-of-input character. I can see that it's getting, modifying, and printing the input. Is that sufficient to confirm that the script will wait for user input (and that the user will be able to intentionally end the input) or is there something else I should do to confirm it waits for all user input until the user intends to end it?
Test 2 - done
Test 3 toy - don't know how to write it...
Even if modified input spit back out is sufficient proof of "waiting for input" for test 1, I also wish to test that a script doesn't consume input on STDIN when no input option (interactive or redirect) is provided - but since it doesn't seem to wait even when I do send it input without an end-of-input signal, how would I test that the script wouldn't hang waiting for input? Note, the script has other options for consuming redirected or piped input, so my intent is specifically to know if it's waiting on input from the tty. All of the STDIN consumption options (whether from the tty or via redirect/pipe) are optional, which is why I want to write these tests.
My manual testing shows everything works as intended. I would just like some tests to assure that behavior for the future.
IO::Pipe::Consumer
I feel like the thing I'm missing is not relevant to IO::Pipe::Consumer, so WRT that, I'll just describe it instead of paste in 30 or so lines of code... All it does is it sets a pipe to the child's STDIN and gives that handle back to the parent for it to print to. I haven't put it on cpan. I'm just experimenting to see if I can use it to write these tests.
IO::Pipe::Consumer is basically the opposite of IO::Pipe::Producer (a module I published on cpan looong ago, say 2001-ish, when I was new to perl, or programming for that matter). The main difference, aside from swapping STDIN for STDOUT and Reader with Writer (and vice versa), is that the open is open(STDIN,"<",\${$stdin_pipe}).
I thought the parent would have to print an "end-of-input" (e.g. "control-d") character to end the input in the test,
Ctrl-D doesn't produce an "end of input character"; it causes the terminal to return EOF.
I don't know what IO::Pipe::Consumer is —it's not on CPAN— but I presume it creates a pipe. Exiting the program causes the writer end of the pipe to be closed and thus cause the reader end to return EOF.
is there something else I should do to confirm it waits for all user input until the user intends to end it?
<> reads until one of the following things happen:
A line feed is encountered (returning what was read including the line feed)
EOF is encountered (returning what was read up to an including the line feed)
An error is encountered (returning false).
You can confirm it waits by putting sleep statements between what you send. Be aware that buffering may interfere.
I am currently writing a QBASIC program that runs an indefinite loop (while loop). However, if a certain condition is met, I want to exit the program. What command do I use, and also what is the syntax.
Thanks
ENDexits program, and clears all variables, which frees up memory.
STOPexits program, but retains the value of all variables, which makes it possible (in certain versions of QB) to continue execution at another point, by choosing Set next statement from the Debugmenu, and then Startfrom the Runmenu. END has the same effect as STOP + choosing Restart from the Runmenu once the program has terminated.
If you have a loop, and want to exit the program from inside it, you may use either
DO
IF condition THEN EXIT DO
LOOP
END
or
DO
IF condition THEN END
LOOP
You're looking for the END or SYSTEM statement. For example:
PRINT "Hello World!"
END
PRINT "This won't be printed."
If you're using regular old QBASIC/QuickBASIC, then you can ignore all of the QB64 details on the linked pages and just use either SYSTEM or END. Both will do the same thing for the most part.1
If you're using FreeBASIC, it's recommended to use END instead of SYSTEM since some things won't get cleaned up properly when you use SYSTEM. See SYSTEM for more information pertaining to FreeBASIC if that's what you're using.
1 The END statement when running the program using QB.EXE /RUN PROGRAM.BAS will print "Press any key to continue" before exiting to the QB/QBASIC environment. The SYSTEM statement when run the same way will simply return you to the DOS shell without any need for a key press. Also, typing SYSTEM in the "Immediate Window" of the QB/QBASIC environment will exit the environment and return to the DOS shell. Otherwise the two statements behave exactly the same in QB/QBASIC, whether for standalone (compiled) programs or .BAS modules.
You can keep any condition according to the need of your program. For eg:
CLS
LET a = 5
WHILE a > 0
PRINT a;
a = a - 1
WEND
END
Here, in the program while wends executes itself until a = 0. This will not run an infinite loop.
The answer is
exit();
to exit the program.
I am trying to write a simple server program in Ocaml that communicates with other processes via a socket. I currently have a problem that the strings the server reads (with input_line ic) do not seem to compare with other strings properly. For example, I run the server program and use telnet to connect to it, if I send "end" as a line, the server program trys to match with "end", but this doesn't work as expected. The function that handles communication is service (below), which is called to handle a client as part of a forking server (something like the double fork treatment here).
let service ic oc
try while true do
let instr = input_line ic in
match instr with
| "end" -> print_endline "matching end" (* this never runs *)
| _ -> output_string oc ((String.uppercase instr) ^ "\n") ; flush oc
done
with End_of_file -> print_endline "Input stream ended."
;;
In fact, if I do print_endline (string_of_bool ("end" = instr)) I always get false (even when I send "end" via telnet). To try and get some sense of what is going I printed out the result of different comparison operations between the let-binding and the try block:
print_endline instr ;
print_endline "end" ;
print_endline (string_of_bool ("end" = instr)) ;
print_endline (string_of_bool ("end" == instr)) ;
print_endline (string_of_int (String.compare "end" instr)) ;
When I send "end" the server now prints out
end
end
false
false
-1
I'm really lost as to what could be going on - I presume it must be something about getting the instr via reading from a socket, as usually you can compare strings just fine.
I don't think I actually had a question in all that background so here are a few variants that could work:
What am I doing wrong?
Why can't I test the input in order to take different actions?
Is this a bug in Ocaml?
Do you need the complete source to figure this out?
My guess is that there are carriage returns in the strings coming in from telnet. As I recall, the old protocols tend to send CRLF at the ends of lines.
You might try printing the string out using String.escaped.
It's pretty unlikely you're seeing a bug in OCaml.
I am iterating through a large test matrix in MATLAB and calling second-party proprietary software (running in MATLAB) each time. I cannot edit the software source code. Sometimes, the software hangs, so I want to exit it after a certain amount of time and move on to the next iteration.
In pseudocode, I'm doing this:
for i = 1:n
output(i) = proprietary_software(input(i));
end
How can I skip to the next iteration (and possibly save output(i)='too_long') if the proprietary software is taking too long?
You will need to call Matlab from another instance of Matlab. The other instance of Matlab will run the command and release control to the first instance of Matlab to wait while it either saves the results or reaches a certain time. In this case, it will wait 30 seconds.
You will need 1 additional function. Make sure this function is on the Matlab path.
function proprietary_software_caller(input)
hTic=tic;
output=proprietary_software(input);
hToc=toc(hTic);
if hToc<30
save('outfile.mat','output');
end
exit;
end
You will need to modify your original script this way
[status,firstPID] = str2double(system('for /f "tokens=2 delims=," %F in (''tasklist /nh /fi "imagename eq Matlab.exe" /fo csv) do #echo %~F'')'));
for i = 1:n
inputStr=num2str(input(i));
system(['matlab.exe -nodesktop -r proprietary_software_caller\(',inputStr,'\)&']);
hTic=tic;
hToc=toc(hTic);
while hToc<30 || ~(exist('outfile.mat','file')==2)
hToc=toc(hTic);
end
if hToc>=30
output(i)= 'too_long';
[status,allPIDs]=str2double(system('for /f "tokens=2 delims=," %F in (''tasklist /nh /fi "imagename eq Matlab.exe" /fo csv) do #echo %~F'')'));
allPIDs(allPIDs==firstPID)=[];
for a=1:numel(allPIDs)
[status,cmdout]=system(['taskkill /F /pid ' sprintf('%i',allPIDs(a))]);
end
elseif exist('outfile.mat','file')==2
loadedData=load('outfile.mat');
output(i)=loadedData.output;
delete('outfile.mat');
end
end
I hope this helps.
You are essentially asking for a way to implement a timeout on MATLAB code. This can be surprisingly tricky to implement. The first thing to state is that if the MATLAB code in question cannot terminate itself, either by exiting cleanly or throwing an error, then it is not possible to terminate the code without quitting or killing the MATLAB process in question. For example, throwing an error in an externally created timer does not work; the error is caught.
The first question to ask is therefore:
Can the over-running code be made to terminate itself?
This depends on the cause to the over-run, and also your access to the source code:
If the program gets stuck in an infinite (or very long-running) loop, either in MATLAB code or a mex file for which you have source code, or which calls a user-defined callback each iteration, then you can get this code to terminate itself.
If the program gets stuck inside a MATLAB builtin, or a p-code file or mex file for which you don't have the source code, and doesn't have support for calling a callback regularly, then it won't be possible for you to get the code to terminate itself.
Let's address the first case. The easiest way to get the code to terminate itself is to get it to throw an error, which is caught by the caller, if it exceeds the timeout time. E.g. in the OP's case:
for i = 1:n
tic();
try
output(i) = proprietary_software(input(i));
catch
end
end
with the following code somewhere in the over-running loop, or called in a loop callback or mex file:
assert(toc() < 10, 'Timed out');
Now for the second case. You need to kill this MATLAB process, so it makes sense for this to be a MATLAB process you have spawned from your current MATLAB session. You can do this using a system call similar to this:
system('matlab -nodisplay -r code_to_run()')
While it is possible for a MATLAB process to quit itself in some situations which could be of use here (e.g. a timer function calling quit('force')), the most reliable way of killing a MATLAB process is to do it with a system call, using taskkill (Windows) or kill (Linux/Mac).
A framework using the approach of spawning and killing timed-out MATLAB processes might work like this:
Using system calls, launch one or more new MATLAB processes from your MATLAB session, running the code you want.
Use the file system or a memory mapped file to communicate between the MATLAB processes the function inputs, loop progress, outputs, process ids and timeout times.
Use the original MATLAB process to check the timeout times haven't been reached, or if so to terminate the process in question and instantiate a new one.
Use the original MATLAB process to collect up the function outputs (either from the filesystem or memory mapped file) and exit. Workers should terminate when there is no more work left
I provide a sketch only because a full working implementation of this approach is fairly involved, and in fact it has already been implemented and is publicly available in the batch_job toolbox. In the OP's case, using this toolbox (with a 10 second timeout) you'd call:
output = batch_job(#proprietary_software, input(:)', '-timeout', 10);
Note that for the toolbox to work, its root directory needs to be on your MATLAB path at startup.
How can I end this loop depending on how long I keep X pressed? If I hold X for five seconds it should send B, S, C, Y, and U at one second intervals.
When I hold X for one second it should only send B, if I hold X for two seconds it should send B and S, etc. Currently it simply sends B, S, C, Y, and U.
*$x::
While(GetKeyState("x", "P"))
{
send b
Sleep 1000
send s
Sleep 1000
send c
Sleep 1000
send y
Sleep 1000
send u
Sleep 1000
}
Return
Solution does not have to be a loop.
x::
index:="i"
letters:="l"
output:="o"
l:="bscyu"
i:=(i<o0?++i:1)
StringSplit,o,l
send % o%i%
sleep,1000
return
x Up::i:=0
I can see a few possible approaches.
1) The first and perhaps worst is to have an if... to test the keystate, and an exit, after every single send. This is extremely repetitive, but not too terrible if you stick it in a function, and just call that, something like:
*$x::
while (GetKeyState("x", "P")) {
sendStuff('b')
sendStuff('s')
sendStuff('c')
...
}
sendStuff(str) {
Send str
if (!GetKeyState("x", "P")) {
exit
}
sleep 1000
}
2) The next is to continue operating as you are, with a chained series of commands, and have an external, separate script kill that series of commands while running, then re-Run() your script when you wish to restart. Killing external scripts is covered in the FAQ, here: http://www.autohotkey.com/docs/FAQ.htm#close
There are three relevant sections there which are a little long to paste here, but in summary, you may be interested in the following commands:
; Allow script's hidden main window to be detected.
DetectHiddenWindows On
; Avoid need to specify full path of file.
SetTitleMatchMode 2
; Kill another script: Update params to the script's case sensitive name.
WinClose Script Filemame.ahk - AutoHotkey
; Suspend other script.
PostMessage, 0x111, 65305,,, Script Filename.ahk - AutoHotkey
; Pause other script.
PostMessage, 0x111, 65306,,, Script Filename.ahk - AutoHotkey
; Pause/resume current script on Ctrl+Alt+P
^!p::Pause
3) There's also a longer code sample just below that, which describes canceling a loop, and it's my belief that this is the correct approach to this problem, as while it might be fiddlier initially, it is considerably more scalable, reduces code duplication, and permits you to handle multiple loop entry/exit conditions in a single place.
It is, in short, the best in terms of Programming Style.
Place the entries (b, s, c, y, u) that you wish to sent into a string, array or other iterable datastructure, and iterate over it, so that your while loop sends only a single item and a pause each iteration. Then the next time you hit your hotkey, you can either resume the loop from where you left off, or start over, depending on whether you maintain a pointer to your current position in the structure.
For example, using the above sendStuff function, a loop will give you the very powerful and trivially extensible:
*$x::
{
letters = b,s,c,y,u
Loop, parse, letters, `,
sendStuff(%A_LoopField%)
return
}
This post is so old, but I just can't help it.
sendChars := "bscyu"
$x::
i := 1 ; (!i ? 1 : i) ; permits starting where left off.
While (getKeyState("x", "P")) {
Send % subStr(sendChars, i, 1)
i := ((i==strLen(sendChars)) ? 1 : (i+1))
if (getKeyState("x", "P")) { ; why wait if you don't have to.
Sleep 1000
}
}
The docs point out that a While loop is only evaluated at the beginning of each iteration, so listing all the keys in a loop will just send all the keys, then break out of loop once at that top again and sees that "x" is no longer being pressed.