I have a small program which runs until a SIGINT is received or two lines (press enter twice) from stdin are received. The react block logic is:
react {
whenever signal(SIGINT) {
say "Got signal";
exit;
}
whenever $*IN.lines.Supply {
say "Got line";
exit if $++ == 1 ;
}
}
Program will exit on two entered lines as expected.
However CTRL-C will not do anything, unless it is followed by a line (enter).
If I switch the order of the whenever blocks, the program is interrupted by a SIGINT but doesn't execute the signal whenever block
react {
whenever $*IN.lines.Supply {
say "Got line";
exit if $++ == 1 ;
}
whenever signal(SIGINT) {
say "Got signal";
exit;
}
}
Is there some other setup required before using the signal sub? Is the order of whenever blocks important in a react block?
Update
So it seems the lines() call is blocking the react block from executing (thanks #Håkon). I kind of get it.
When comparing to a similar code structure for reading a socket I'm confused though. The presence of data (or lack of) has no effect on the signal handler executing and it can read lines just fine in this example:
my $listener=IO::Socket::Async.listen("0.0.0.0",4432);
react {
whenever $listener {
whenever $_.Supply.lines() {
say "Got line";
}
}
whenever signal(SIGINT) {
say "Got signal";
exit;
}
}
#testing with:
# curl http://localhost:4432
Why does this behave so different to my original code?
The order doesn't matter provided the data sources really behave in an asynchronous manner, which unfortunately is not the case here. The Supply coercer on a Seq does not introduce any concurrency, and does immediately try to produce a value to emit on the Supply, which in turn blocks on reading from $*IN. Thus, the second subscription doesn't have chance to be set up; the same underlying issue causes the other problems observed.
The solution is to force the reading to happen "elsewhere". We can do that with Supply.from-list(...), plus telling it we really do want to use the current scheduler rather than its default CurrentThreadScheduler. Thus, this behaves as wanted:
react {
whenever Supply.from-list($*IN.lines, scheduler => $*SCHEDULER) {
say "Got line";
exit if $++ == 1 ;
}
whenever signal(SIGINT) {
say "Got signal";
exit;
}
}
It's likely this area will be revised somewhat in future Perl 6 versions. The current behavior was well-intended; the design principle was to avoid implicit introduction of concurrency, following the general principle that supplies are a tool for managing concurrency that inherently exists, rather than for introducing it. However, in reality, the lack of concurrency here has probably tripped up more folks than it has helped. (Further, we may look into offering real non-blocking file I/O, rather than building it from sync file I/O + threads.)
Here is a variant that runs the signal handler (based on this answer), but unfortunately autoflushing of $*IN seems to be turned off:
my $lines = supply {
whenever start $*IN.lines.Supply {
whenever .lines { .emit }
}
}.Channel;
react {
whenever signal(SIGINT) {
say "Got signal";
exit;
}
whenever $lines {
say "Got line: '{$_}'";
exit if $++ == 1;
}
}
Now you have to press CTRL-D to print the lines, and then it print all lines entered as a concatenated string and after that $*IN is closed.. How can I turn on autoflushing for $*IN in this case?
Related
I want to print the current time every second, and also want to sleep 10 seconds very 5 seconds:
react {
whenever Supply.interval(1) {
say DateTime.now.posix;
}
whenever Supply.interval(5) {
sleep 10;
say 'Sleep Done';
}
whenever signal(SIGINT) {
say "Done.";
done;
}
}
the output is not what i wanted:
1542371045
Sleep Done
1542371055
Sleep Done
1542371065
Sleep Done
1542371075
Done.
...
what i want is this:
1542371045
1542371046
1542371047
1542371048
1542371049
Sleep Done
1542371059
1542371060
1542371061
1542371062
1542371063
Sleep Done
Done.
Don't know much about Promise, Supply... about Raku, is this possible?
Depending on exactly what else was needed, I'd probably write it something like this:
react {
sub sequence() {
whenever Supply.interval(1).head(5) {
say DateTime.now.posix;
LAST whenever Promise.in(10) {
say "Sleep done";
sequence();
}
}
}
sequence();
}
Which gives output like this:
1542395158
1542395159
1542395160
1542395161
1542395162
Sleep done
1542395172
1542395173
1542395174
1542395175
1542395176
Sleep done
1542395186
1542395187
1542395188
...
This will make absolutely sure you get 5 ticks out between the 10s pauses; doing it with two separate interval supplies - as in many solutions here - will not give any strict guarantees of that, and could miss a tick now and then. (One that doesn't is the cute one with rotor, which is a good bet if you don't need to actually print the "sleep done" thing). It's also free of state (variables) and conditions, which is rather nice.
While this looks like it might be recursive, since whenever is an asynchronous looping construct, it will not actually build up a call stack at all.
It's also fully built of asynchronous constructs, and so in Perl 6.d will not - if the react is triggered on the thread pool - ever block a real OS thread. So you could have thousands of these active. By contrast, sleep will block a real thread, which is what sleep traditionally would be expected to do, but isn't such a good fit if otherwise dealing with asynchronous constructs.
One mistake you are making is that you are assuming that supplies will lose values, or you are assuming they will stop generating values while the react is blocked.
They won't.
They keep generating values.
You should also try to have the code in a whenever run for as short of a time as possible.
(Pretend it is a CPU interrupt handler.)
There may be some exceptions to this rule, particularly for supply blocks.
Using the structure that you provided, this is one way to achieve what you want:
react {
# Are we ignoring the interval(1) values?
my Bool:D $ignore = False;
# The sleeping status of interval(5).
my Promise:D $sleep .= kept;
whenever Supply.interval(1) {
# Skip if it is supposed to be blocked.
next if $ignore;
say DateTime.now.posix;
}
# First one runs immediately, so skip it.
whenever Supply.interval(5).skip {
# Don't run while the “sleep” is pending.
next unless $sleep.status; # Planned
if $ignore {
$ignore = False;
say 'Sleep Done';
} else {
$ignore = True;
# Must be less than the multiple of 5 we want
# otherwise there may be a race condition.
$sleep = Promise.in(9);
}
}
whenever signal(SIGINT) {
say "Done.";
done;
}
}
That isn't very clear.
How about we just use .rotor instead, to skip every third interval of 5?
react {
my Bool:D $ignore = True;
# Note that first one runs immediately. (no .skip)
# We also want it to always be a few milliseconds before
# the other Supply, so we put it first.
# (Should have done that with the previous example as well.)
whenever Supply.interval(5).rotor(1, 1 => 1) {
$ignore = !$ignore;
}
whenever Supply.interval(1) {
next if $ignore;
say DateTime.now.posix;
}
whenever signal(SIGINT) {
say "Done.";
done;
}
}
While we are at it, why not just use .rotor on the .interval(1) Supply?
react {
whenever Supply.interval(1).rotor(1 xx 4, 1 => 10) {
say DateTime.now.posix;
}
whenever signal(SIGINT) {
say "Done.";
done;
}
}
Note that we can't just use 5 => 10 because that batches them up, and we want them to be run singly.
Note that .grep also works on Supplys, so we could have used that instead to check the $ignored value.
react {
my Bool:D $ignore = True;
whenever Supply.interval(5).rotor(1, 1 => 1) {
$ignore = !$ignore;
}
whenever Supply.interval(1).grep({ !$ignore }) {
say DateTime.now.posix;
}
whenever signal(SIGINT) {
say "Done.";
done;
}
}
Maybe this can work:
loop {
react {
whenever Supply.interval(1) {
say DateTime.now.posix;
}
whenever Promise.in(5) {
done;
}
whenever signal(SIGINT) {
say "Done.";
done;
}
}
sleep 10;
}
The output is:
1542347961
1542347962
1542347963
1542347964
1542347965
1542347976 # <- 10s
1542347977
1542347978
1542347979
1542347980
1542347991 # <- 10s
The thing is the two Supplies are effectively running in different threads so don't interact with each other. Your sleep only puts the thread it's in to sleep (and then the fact it's a 5 second interval creates another sleep anyway).
To achieve the result you're looking for I went with this which uses the single 1 second interval and a couple of flags.
react {
whenever Supply.interval(1) {
state $slept = False;
state $count = 0;
if $count >= 0 {
if $slept {
say "Sleep Done";
$slept = False
}
say DateTime.now.posix;
}
$count++;
if ( $count == 5 ) {
$count = -9;
$slept = True
}
}
whenever signal(SIGINT) {
say "Done.";
done;
}
}
Note that we have to use state variables because the whenever block is effectively executed in it's own thread each second. The state variables allow us to keep track of the current situation.
If it was running on a smaller interval I would maybe think about using atomic ints instead of normal ones (in case the code was executed while it was still running) but that block should never take more than a second to execute so I don't think it's a problem.
Because only one whenever will be executing at any time, the sleep in there will be halting all handling of things to react to. The easiest way to achieve what you want, is to do the sleep as an asynchronous job by wrapping the code of that whenever into a start block.
react {
whenever Supply.interval(1) {
say DateTime.now.posix;
}
whenever Supply.interval(5) {
start {
sleep 10;
say 'Sleep Done';
}
}
whenever signal(SIGINT) {
say "Done.";
done;
}
}
This gives the desired output, as far as I can see.
I'm trying to do something like this
$SIG{ALRM} = sub {
print $line_number_when_alarm_went_off;
};
alarm 10;
# rest of the script
I'm using ALRM as an example, I will end up using a different signal to kill from the outside to trigger it. Is there a neat way of doing this sort of operation?
I have some slow scripts and sometimes I would like to send them a signal to know where the code is at that moment.
I want to make this as unobtrusive as possible so I could package it and add it to legacy code.
You can use caller in list context to get the package, file and line number of the place that the current sub got called from.
$SIG{ALRM} = sub {
my ($pkg, $file, $line) = caller;
CORE::say $line;
die;
};
alarm 2;
while (1) {
1;
}
This will output 11 (if I counted correctly, in my file it's 1740, and the $SIG line is 1730.
It also works with other signal handlers, like warn.
$SIG{__WARN__} = sub {
my ($pkg, $file, $line) = caller;
CORE::say $line;
};
warn 'foo';
This will output 7
Note that your code has a syntax error. You are assigning a hash reference as a signal handler, not a sub reference!
I see the following code in Perl 6:
await do for #files -> $file {
start {
#do something ... }
}
which runs in async mode.
Why does the above code need do? What is the purpose of do in Perl 6? Could someone please explain the above code in detail?
Also is there are an option to write something like this:
for #files -> $file {
start {
#do something ... }
}
and await after the code for the promises to be fulfilled?
The purpose of do
The for keyword can be used in two different ways:
1) As a stand-alone block statement:
for 1..5 { say $_ }
2) As a statement modifier appended to the end of a statement:
say $_ for 1..5;
When the bare for keyword is encountered in the middle of a larger statement, it is interpreted as that second form.
If you want to use the block form inside a larger statement (e.g. as the argument to the await function), you have to prefix it with do to tell the parser that you're starting a block statement here, and want its return value.
More generally, do makes sure that what follows it is parsed using the same rules it would be parsed as if it were its own statement, and causes it to provide a return value. It thus allows us to use any statement as an expression inside a larger statement. do if, do while, etc. all work the same way.
Explanation of your code
The code you showed...
await do for #files -> $file {
start {
#do somthing ... }
}
...does the following:
It loops of over the array #files.
For each iteration, it uses the start keyword to schedule an asynchronous task, which presumably does something with the current element $file. (The $*SCHEDULER variable decides how the task is actually started; by default it uses a simple thread pool scheduler.)
Each invocation of start immediately returns a Promise that will be updated when the asynchronous task has completed.
The do for collects a sequence of all the return values of the loop body (i.e. the promises).
The await function accepts this sequence as its argument, and waits until all the promises have completed.
How to "await after the code"
Not entirely sure what you mean here.
If you want to remember the promises but not await them just jet, simply store them in an array:
my #promises = do for #files -> $file {
start {
#do something ... }
}
#other code ...
await #promises;
There is no convenience functionality for awaiting all scheduled/running tasks. You always have to keep track of the promises.
I am in the process of writing a bash clone in Rust. I need to have my program exit when the user types exit. In previous iterations of my program, before I added more complicated features, I used return to get out of the loop that was prompting the user for input. This logic is now in a function, because of the way I am implementing built in shell functions, so when I return it just jumps out of the function back into the control loop, instead of short-circuiting the control loop and ending the program.
I realize that I could probably return a boolean when the user types exit and exit the loop, but I would like to at least know if Rust has a way to terminate programs early, similar to Java's System.exit(), as this is useful for certain types of programs.
Rust 1.0 stable
std::process::exit() does exactly that - it terminates the program with the specified exit code:
use std::process;
fn main() {
for i in 0..10 {
if i == 5 {
process::exit(1);
}
println!("{}", i);
}
}
This function causes the program to terminate immediately, without unwinding and running destructors, so it should be used sparingly.
Alternative (not recommended) solution
You can use C API directly. Add libc = "0.2" to Cargo.toml, and:
fn main() {
for i in 0..10 {
if i == 5 {
unsafe { libc::exit(1); }
}
println!("{}", i);
}
}
Calling C functions cannot be verified by the Rust compiler, so this requires the unsafe block. Resources used by the program will not be freed properly. This may cause problems such as hanging sockets.
As far as I understand, the proper way to exit from the program is to terminate all threads somehow, then the process will exit automatically.
panic!("Oh no something bad has happened!")
Example:
if a * g < 0f32 { panic!("The arithmetric-geometric mean is undefined for numbers less than zero!"); }
In older documentation, you will see this as fail!("Oh no something bad here has happened.")
For some reason, this macro was changed from fail to panic. Panic is the way to fail, if you must.
[edit] I am sorry. It looks like you should be testing input for the string "exit," which would depend on how you are taking input (by line or by args). Then you can have the program break out of the loop on the condition that the exit is detected.
Example:
loop {
if exit_found { break }
else {
// your thing, which also looks for exit_found
}
}
i am processing a ragged semicolon delimited file using script component as transformation.
The component is able to process the data and load to oledb destination. But when error is found it should stop processing further. As i am using try catch block the component doesn't fail and continue to process till the end.
Is there any way i could stop the processing further without failing the component/package?
Let me know if any other information/details required?
sample code:
str.split(";");
if(column[0] == "H")
{
col1=Column[3];
}
if(column[0] != "T")
{
try
{
Row.col1=Column[0];
Row.col2=Column[1];
.....
}
catch
{
update the variable to check if we have error in file.
}
}
Thank you for your time.
The general idea will be that you want to use try/catch blocks to ensure the data processing itself doesn't abort. Once you know your script isn't reporting a failure back to the engine, it's a simple process to not call the AddRow()
Pseudocode
foreach(line in fileReader)
{
try
{
// perform dangerous operations here
// Only add row if you have been able to parse current line
Output0Buffer.AddRow();
Output0Buffer.Col1 = parsedContent;
}
catch
{
// Signal that we should break out of the loop
// do not propagate the error
// You might want to do something though so you know you
// have an incomplete load
break;
}
}
If you are looking to just skip the current bad line, you can substitute continue for the break above.
C# loop - break vs. continue
I didn't get any help from anywhere, But as a work around i have placed a return statement in the code. It checks the error variable if it's true then i will return without processing further. But the thing still is it processes the whole file :(. But it works!!!