From d9d0cfd42ccdee03085f36fed194d850622804b9 Mon Sep 17 00:00:00 2001 From: chenglch Date: Thu, 8 Jun 2017 11:21:26 +0800 Subject: [PATCH] Avoid of circular reference in a loop of rinstall (#3121) This is a temporary fix for getadapter which will hang forever if error happens in `rinstall stage`. The root cause is the circular reference in `runxcmd`. As global variable `$::xcmd_outref` and `%::xcmd_outref_hash` are used to save the output message, if the plugin command are called with runxcmd and the plugin called also calls another plugin with `runxcmd`, the circular reference will happen. In this situation, if the output reponse is used in a iterator, like: ``` foreach my $line (@$res) { xCAT::MsgUtils->message("I", $rsp, $callback); ``` `$res` points to the global variable, and `MsgUtils->message` in the runxcmd calls also add the value in the global variable, as the iter object is changed, the loop will not be terminated. This patch can not solve the circular reference problem, it is just a workaround to avoid infinite loop. Some known issues: the error message will print twice as the `MsgUtils->message` called in runxcmd. But we can not simply remove it as the plugin may not be called with `runxcmd`. Error message example: ``` Error: frame10node10: mgt configuration can not be found. frame10node10: Unable to identify plugin for this command, check relevant tables: noderes.netboot frame10node10: Unable to identify plugin for this command, check relevant tables: noderes.netboot Failed to run 'nodeset' against the following nodes: frame10node10 Error: failed to run command: rinstall frame10node10 runcmd=getadapter ``` partial-fix: #3046 --- xCAT-server/lib/xcat/plugins/rinstall.pm | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/rinstall.pm b/xCAT-server/lib/xcat/plugins/rinstall.pm index 4fba96ed0..906746b33 100644 --- a/xCAT-server/lib/xcat/plugins/rinstall.pm +++ b/xCAT-server/lib/xcat/plugins/rinstall.pm @@ -351,7 +351,9 @@ sub rinstall { # We got an error with the nodeset my @successnodes; my @failurenodes; - foreach my $line (@$res) { + # copy into a temporary variable to avoid of circular reference + my @lines = @$res; + foreach my $line (@lines) { $rsp->{data}->[0] = $line; if (($line =~ /: install/) or ($line =~ /: netboot/)) { my $successnode; @@ -414,7 +416,6 @@ sub rinstall { }, $subreq, -1, 1); - $rc = $::RUNCMD_RC; my $rsp = {}; if ($VERBOSE) { @@ -427,7 +428,9 @@ sub rinstall { # We got an error with the rnetboot my @failurenodes; - foreach my $line (@$res) { + # copy into a temporary variable to avoid of circular reference + my @lines = @$res; + foreach my $line (@lines) { $rsp->{data}->[0] = $line; if ($line =~ /: Success/) { my $successnode; @@ -491,7 +494,9 @@ sub rinstall { # We got an error with the rsetboot my @successnodes; my @failurenodes; - foreach my $line (@$res) { + # copy into a temporary variable to avoid of circular reference + my @lines = @$res; + foreach my $line (@lines) { $rsp->{data}->[0] = $line; if ($line =~ /: Network/) { my $successnode; @@ -550,7 +555,9 @@ sub rinstall { unless ($rc == 0) { # We got an error with the rpower my @failurenodes; - foreach my $line (@$res) { + # copy into a temporary variable to avoid of circular reference + my @lines = @$res; + foreach my $line (@lines) { $rsp->{data}->[0] = $line; if (($line =~ /: on reset/) or ($line =~ /: off on/)) { my $successnode;