[pve-devel] [RFC common 2/2] REST environment: fork worker: install custom __WARN__ handler

Fiona Ebner f.ebner at proxmox.com
Mon Feb 5 13:28:54 CET 2024

So all warnings will be treated consistently inside a worker task. In
particular, all warnings will count towards the task warning count and
be more visible in the UI. Avoids the need to switch existing warnings
to log_warn().

When pvedaemon forked a worker, the worker would inherit its __WARN__
handler and also log any warnings to syslog, so make sure those
warnings are not less visible than before, by also logging to syslog.

The same warning would not show up in syslog when the task was invoked
via the CLI instead, which was another inconsistency.

The __WARN__ handler needs to increment the warning_count for warnings
issued with Perl's warn. But then in RESTEnvironment.pm's warn method,
warning_count cannot be incremented anymore, because otherwise a call
to log_warn() would increment it once, call warn, and then the
__WARN__ handler would increment it again. The variable is only ever
read in fork_worker(), so it is safe to just move the code
incrementing it to the __WARN__ handler, because that will be called
by both, Perl's warn and log_warn().

This effectively makes log_warn() and RESTEnvironment.pm's warn method
not worth using anymore, so deprecate them.

Signed-off-by: Fiona Ebner <f.ebner at proxmox.com>
 src/PVE/RESTEnvironment.pm | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/PVE/RESTEnvironment.pm b/src/PVE/RESTEnvironment.pm
index 41efb16..8394e2e 100644
--- a/src/PVE/RESTEnvironment.pm
+++ b/src/PVE/RESTEnvironment.pm
@@ -537,6 +537,17 @@ sub fork_worker {
+	$SIG{'__WARN__'} = sub {
+	    my $err = $@;
+	    my $message = $_[0];
+	    chomp($message);
+	    $message =~ s/^WARN: //; # avoid duplicate prefix when triggered by log_warn()
+	    print STDERR "WARN: $message\n";
+	    syslog('warning', $message);
+	    $self->{warning_count}++;
+	    $@ = $err;
+	};
 	my $ppgid;
 	# set session/process group allows to kill the process group
 	if ($sync && -t STDIN) {
@@ -716,6 +727,9 @@ sub fork_worker {
     return wantarray ? ($upid, $res) : $upid;
+# NOTE: Deprecated - remove once all callers are gone
+# This was introduced for counting task warnings, which is now done via a __WARN__ handler inside
+# fork_worker().
 sub log_warn {
     my ($message) = @_;
@@ -727,14 +741,14 @@ sub log_warn {
+# NOTE: Deprecated - remove once all callers are gone
+# Remove once all users are gone
 sub warn {
     my ($self, $message) = @_;
     warn "WARN: $message\n";
-    $self->{warning_count}++;
 # Abstract function

More information about the pve-devel mailing list