如果推送线程在 Perl 中有异常,则停止应用程序
stop application if pushed thread had exception in Perl
我有一个以并行模式运行的应用程序。作业正在使用带有已实现子例程的线程运行。子程序“worker3”有三个参数,一个参数和两个文件路径。
此子例程使用系统命令执行 R 脚本。
if ($ENV{"model"} eq "alaef_cy40_5km"){
sub worker3 {
my $parameter2 = $_[0];
print $parameter2, "\n";
$ENV{"grb_path"} = $models{$model}{"grb"}{"path"}{$parameter2};
$ENV{"grb_file"} = $models{$model}{"grb"}{"file"}{$parameter2};
print"FROM sub:", "\n";
print $ENV{"grb_path"}, "\n";
print $ENV{"grb_file"}, "\n";
say "Job Started\n";
system("Rscript $root/read_ALAEF.R @_ ");
}
for my $param( 'T2m','RH2m'){
push @threads, my $thr1=threads ->create('worker3', $param ,$ENV{"grb_file"},$ENV{"grb_path"})
}
$_->join() for threads->list();
}
问题是当 R 脚本完成并暂停执行时,应用程序最终状态正常。我需要的是当 R 脚本出错时,整个程序需要停止。
所以,如果一个线程失败,应用程序需要停止,并显示错误。
这是输出:
T2m
FROM sub:
/data/nwp/products/a-laef_stream
A-LAEF_mem_{MBR2}_{YYYY}{MM}{DD}{HH}_surface.grb
Job Started
RH2m
FROM sub:
/data/nwp/products/a-laef_stream
A-LAEF_mem_{MBR2}_{YYYY}{MM}{DD}{HH}_surface.grb
Job Started
-- Attaching packages --------------------------------------- tidyverse 1.3.1 --
v ggplot2 3.3.5 v purrr 0.3.4
v tibble 3.1.6 v dplyr 1.0.7
v tidyr 1.1.4 v stringr 1.4.0
v readr 2.1.0 v forcats 0.5.1
-- Attaching packages --------------------------------------- tidyverse 1.3.1 --
v ggplot2 3.3.5 v purrr 0.3.4
v tibble 3.1.6 v dplyr 1.0.7
v tidyr 1.1.4 v stringr 1.4.0
v readr 2.1.0 v forcats 0.5.1
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
here() starts at /work/users/p6095/2022-02-19_00/harp.119
Loading required package: harpIO
Attaching package: 'harpIO'
The following object is masked from 'package:purrr':
accumulate
Loading required package: harpPoint
Loading required package: harpVis
Loading required package: shiny
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
here() starts at /work/users/p6095/2022-02-19_00/harp.119
Loading required package: harpIO
Attaching package: 'harpIO'
The following object is masked from 'package:purrr':
accumulate
Loading required package: harpPoint
Loading required package: harpVis
Loading required package: shiny
Loading required package: harpSpatial
Error: unexpected string constant in:
"
'4'"
Execution halted
Loading required package: harpSpatial
Error: unexpected string constant in:
"
'4'"
Execution halted
----------------------------------------------------
Application finished OK at: 21-02-2022 15:46:11 UTC
----------------------------------------------------
如你所见,它表明应用程序完成正常,无论是否是 R 代码中的错误。我需要这个:如果推送线程有异常 -> 停止应用程序 perl
这是一个示例,说明如果给定线程的其中一个可执行文件 运行 失败,您可以如何使用状态消息停止主程序:
首先,我构建了一个虚拟可执行文件 foo.pl
,如下所示:
use feature qw(say);
use strict;
use warnings;
my ($id, $force_fail) = @ARGV;
my $thread1_exit_value = $force_fail ? 2 : 0;
if ($id == 1) {
sleep 2;
exit $thread1_exit_value;
}
elsif ($id == 2) {
sleep 5;
exit 0;
}
那么主程序是这样的:
use v5.20; # experimental signatures requires perl >= 5.20
use feature qw(say);
use strict;
use warnings;
use experimental qw(signatures);
use threads;
{
my @threads;
my $force_fail = 1;
my $start_time = time;
for (1..2) {
my $thr = threads->create(
sub {
my $res = system "foo.pl", $_, $force_fail; $res
}
);
push @threads, $thr;
}
my $fail = 0;
for my $i (0..$#threads) {
my $thr = $threads[$i];
if ($fail) {
say "detaching thread $i..";
$thr->detach();
}
else {
say "joining thread $i..";
my $res = $thr->join();
if (command_failed($res, $i)) {
$fail = 1;
}
}
}
my $total_time = time - $start_time;
say "Program " . ($fail ? "failed" : "succeeded") . " after $total_time seconds";
}
sub command_failed( $res, $id ) {
if ($res == -1) {
say "thread $id failed to execute: $!";
return 1;
}
elsif ($res & 127) {
printf "thread $id died from signal %d\n", $res & 127;
return 1;
}
else {
my $rcode = $res >> 8;
if ($rcode != 0) {
say "thread $id exited with return value $rcode";
return 1;
}
return 0;
}
}
在主脚本第9行设置$force_fail = 1
时,输出为:
joining thread 0..
thread 0 exited with return value 2
detaching thread 1..
Program failed after 2 seconds
另一方面,当设置 $force_fail = 0
时,输出为:
joining thread 0..
joining thread 1..
Program succeeded after 5 seconds
我有一个以并行模式运行的应用程序。作业正在使用带有已实现子例程的线程运行。子程序“worker3”有三个参数,一个参数和两个文件路径。 此子例程使用系统命令执行 R 脚本。
if ($ENV{"model"} eq "alaef_cy40_5km"){
sub worker3 {
my $parameter2 = $_[0];
print $parameter2, "\n";
$ENV{"grb_path"} = $models{$model}{"grb"}{"path"}{$parameter2};
$ENV{"grb_file"} = $models{$model}{"grb"}{"file"}{$parameter2};
print"FROM sub:", "\n";
print $ENV{"grb_path"}, "\n";
print $ENV{"grb_file"}, "\n";
say "Job Started\n";
system("Rscript $root/read_ALAEF.R @_ ");
}
for my $param( 'T2m','RH2m'){
push @threads, my $thr1=threads ->create('worker3', $param ,$ENV{"grb_file"},$ENV{"grb_path"})
}
$_->join() for threads->list();
}
问题是当 R 脚本完成并暂停执行时,应用程序最终状态正常。我需要的是当 R 脚本出错时,整个程序需要停止。 所以,如果一个线程失败,应用程序需要停止,并显示错误。
这是输出:
T2m
FROM sub:
/data/nwp/products/a-laef_stream
A-LAEF_mem_{MBR2}_{YYYY}{MM}{DD}{HH}_surface.grb
Job Started
RH2m
FROM sub:
/data/nwp/products/a-laef_stream
A-LAEF_mem_{MBR2}_{YYYY}{MM}{DD}{HH}_surface.grb
Job Started
-- Attaching packages --------------------------------------- tidyverse 1.3.1 --
v ggplot2 3.3.5 v purrr 0.3.4
v tibble 3.1.6 v dplyr 1.0.7
v tidyr 1.1.4 v stringr 1.4.0
v readr 2.1.0 v forcats 0.5.1
-- Attaching packages --------------------------------------- tidyverse 1.3.1 --
v ggplot2 3.3.5 v purrr 0.3.4
v tibble 3.1.6 v dplyr 1.0.7
v tidyr 1.1.4 v stringr 1.4.0
v readr 2.1.0 v forcats 0.5.1
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
here() starts at /work/users/p6095/2022-02-19_00/harp.119
Loading required package: harpIO
Attaching package: 'harpIO'
The following object is masked from 'package:purrr':
accumulate
Loading required package: harpPoint
Loading required package: harpVis
Loading required package: shiny
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
here() starts at /work/users/p6095/2022-02-19_00/harp.119
Loading required package: harpIO
Attaching package: 'harpIO'
The following object is masked from 'package:purrr':
accumulate
Loading required package: harpPoint
Loading required package: harpVis
Loading required package: shiny
Loading required package: harpSpatial
Error: unexpected string constant in:
"
'4'"
Execution halted
Loading required package: harpSpatial
Error: unexpected string constant in:
"
'4'"
Execution halted
----------------------------------------------------
Application finished OK at: 21-02-2022 15:46:11 UTC
----------------------------------------------------
如你所见,它表明应用程序完成正常,无论是否是 R 代码中的错误。我需要这个:如果推送线程有异常 -> 停止应用程序 perl
这是一个示例,说明如果给定线程的其中一个可执行文件 运行 失败,您可以如何使用状态消息停止主程序:
首先,我构建了一个虚拟可执行文件 foo.pl
,如下所示:
use feature qw(say);
use strict;
use warnings;
my ($id, $force_fail) = @ARGV;
my $thread1_exit_value = $force_fail ? 2 : 0;
if ($id == 1) {
sleep 2;
exit $thread1_exit_value;
}
elsif ($id == 2) {
sleep 5;
exit 0;
}
那么主程序是这样的:
use v5.20; # experimental signatures requires perl >= 5.20
use feature qw(say);
use strict;
use warnings;
use experimental qw(signatures);
use threads;
{
my @threads;
my $force_fail = 1;
my $start_time = time;
for (1..2) {
my $thr = threads->create(
sub {
my $res = system "foo.pl", $_, $force_fail; $res
}
);
push @threads, $thr;
}
my $fail = 0;
for my $i (0..$#threads) {
my $thr = $threads[$i];
if ($fail) {
say "detaching thread $i..";
$thr->detach();
}
else {
say "joining thread $i..";
my $res = $thr->join();
if (command_failed($res, $i)) {
$fail = 1;
}
}
}
my $total_time = time - $start_time;
say "Program " . ($fail ? "failed" : "succeeded") . " after $total_time seconds";
}
sub command_failed( $res, $id ) {
if ($res == -1) {
say "thread $id failed to execute: $!";
return 1;
}
elsif ($res & 127) {
printf "thread $id died from signal %d\n", $res & 127;
return 1;
}
else {
my $rcode = $res >> 8;
if ($rcode != 0) {
say "thread $id exited with return value $rcode";
return 1;
}
return 0;
}
}
在主脚本第9行设置$force_fail = 1
时,输出为:
joining thread 0..
thread 0 exited with return value 2
detaching thread 1..
Program failed after 2 seconds
另一方面,当设置 $force_fail = 0
时,输出为:
joining thread 0..
joining thread 1..
Program succeeded after 5 seconds