From: Elias Huhsovitz <e.huhsovitz@proxmox.com>
To: pve-devel@lists.proxmox.com
Cc: Elias Huhsovitz <e.huhsovitz@proxmox.com>
Subject: [PATCH container 2/2] fix #8093: console: bind console sessions to container lifetime via systemd scopes
Date: Wed, 7 Oct 2026 10:37:26 +0200 [thread overview]
Message-ID: <20261007083726.26067-3-e.huhsovitz@proxmox.com> (raw)
In-Reply-To: <20261007083726.26067-1-e.huhsovitz@proxmox.com>
Console processes can outlive their useful session when a container
stops or disappears while a console is attached. The previous cleanup
ran in pvestatd, which polled every 10s: forked lxc-info for every
running container, and killed orphaned processes by their PID.
Manage console lifetime in the container lifecycle instead. Add
wrap_in_console_scope() to start console commands in a systemd scope.
Bind each scope with PartOf= to the respective pve-container service.
Use the wrapper for pct console/enter/exec, and the API console
endpoints.
When the container service stops, systemd stops the related console
scopes.
Signed-off-by: Elias Huhsovitz <e.huhsovitz@proxmox.com>
---
src/PVE/API2/LXC.pm | 6 +++---
src/PVE/CLI/pct.pm | 10 +++++++---
src/PVE/LXC.pm | 41 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 51 insertions(+), 6 deletions(-)
diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 5f94d5a..3fd2bf8 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -1015,7 +1015,7 @@ __PACKAGE__->register_method({
my $ticket = PVE::AccessControl::assemble_vnc_ticket($authuser, $authpath, $port);
my $conf = PVE::LXC::Config->load_config($vmid, $node);
- my $concmd = PVE::LXC::get_console_command($vmid, $conf, -1);
+ my $concmd = PVE::LXC::get_console_command_scoped($vmid, $conf, -1);
my $shcmd = [
'/usr/bin/dtach',
@@ -1146,7 +1146,7 @@ __PACKAGE__->register_method({
my $ticket = PVE::AccessControl::assemble_vnc_ticket($authuser, $authpath, $port);
my $conf = PVE::LXC::Config->load_config($vmid, $node);
- my $concmd = PVE::LXC::get_console_command($vmid, $conf, -1);
+ my $concmd = PVE::LXC::get_console_command_scoped($vmid, $conf, -1);
my $shcmd = [
'/usr/bin/dtach',
@@ -1288,7 +1288,7 @@ __PACKAGE__->register_method({
die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
- my $concmd = PVE::LXC::get_console_command($vmid, $conf);
+ my $concmd = PVE::LXC::get_console_command_scoped($vmid, $conf);
my $shcmd = [
'/usr/bin/dtach',
diff --git a/src/PVE/CLI/pct.pm b/src/PVE/CLI/pct.pm
index ceb0bea..11e85bc 100755
--- a/src/PVE/CLI/pct.pm
+++ b/src/PVE/CLI/pct.pm
@@ -153,7 +153,7 @@ __PACKAGE__->register_method({
# test if container exists on this node
my $conf = PVE::LXC::Config->load_config($param->{vmid});
- my $cmd = PVE::LXC::get_console_command($param->{vmid}, $conf, $param->{escape});
+ my $cmd = PVE::LXC::get_console_command_scoped($param->{vmid}, $conf, $param->{escape});
exec(@$cmd);
},
});
@@ -207,7 +207,9 @@ __PACKAGE__->register_method({
my @lxc_attach_cmd = ('lxc-attach', '-n', $vmid);
push @lxc_attach_cmd, $keep_env ? '--keep-env' : '--clear-env';
- exec(@lxc_attach_cmd);
+
+ my $scoped_cmd = PVE::LXC::wrap_in_console_scope($vmid, \@lxc_attach_cmd);
+ exec(@$scoped_cmd);
},
});
@@ -250,7 +252,9 @@ __PACKAGE__->register_method({
my @lxc_attach_cmd = ('lxc-attach', '-n', $vmid);
push @lxc_attach_cmd, $keep_env ? '--keep-env' : '--clear-env';
push @lxc_attach_cmd, '--', @{ $param->{'extra-args'} };
- exec(@lxc_attach_cmd);
+
+ my $scoped_cmd = PVE::LXC::wrap_in_console_scope($vmid, \@lxc_attach_cmd);
+ exec(@$scoped_cmd);
},
});
diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index dee073d..14bc6e4 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -954,6 +954,39 @@ sub verify_searchdomain_list {
return join(' ', @list);
}
+=head2 wrap_in_console_scope
+
+Wraps a command array in a transient systemd scope and binds it to the
+container's main systemd service. This ensures the console process is
+automatically terminated by systemd when the container stops, preventing
+orphaned processes without requiring manual cleanup scripts.
+
+=cut
+
+sub wrap_in_console_scope {
+ my ($vmid, $cmd) = @_;
+
+ my $session_id = "$$-" . time();
+ my $unit_name = "pve-lxc-console-$vmid-$session_id";
+
+ my $service = "pve-container\@$vmid.service";
+ # service name appends "-debug" when container is started in debug mode
+ my $debug_service = "pve-container-debug\@$vmid.service";
+
+ my @scope_cmd = (
+ 'systemd-run',
+ '--scope',
+ '--unit', $unit_name,
+ '--description', "PVE LXC Console for $vmid",
+ '--property', "PartOf=$service $debug_service",
+ '--quiet',
+ );
+
+ push @scope_cmd, @$cmd;
+
+ return \@scope_cmd;
+}
+
sub get_console_command {
my ($vmid, $conf, $escapechar) = @_;
@@ -978,6 +1011,14 @@ sub get_console_command {
return $cmd;
}
+sub get_console_command_scoped {
+ my ($vmid, $conf, $escapechar) = @_;
+
+ my $cmd = get_console_command($vmid, $conf, $escapechar);
+
+ return wrap_in_console_scope($vmid, $cmd)
+}
+
sub get_primary_ips {
my ($conf) = @_;
--
2.47.3
next prev parent reply other threads:[~2026-10-07 8:37 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-07 8:37 [PATCH container/manager 0/2] fix #8093: console: bind console sessions to container lifetime via systemd scopes Elias Huhsovitz
2026-10-07 8:37 ` [PATCH manager 1/2] fix #8093: pvestatd: remove cleanup of stale lxc consoles Elias Huhsovitz
2026-10-07 8:37 ` Elias Huhsovitz [this message]
2026-10-07 13:38 ` [PATCH container/manager 0/2] fix #8093: console: bind console sessions to container lifetime via systemd scopes Filip Schauer
2026-10-08 10:25 ` Elias Huhsovitz
2026-10-08 13:15 ` Filip Schauer
2026-10-09 9:44 ` Elias Huhsovitz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261007083726.26067-3-e.huhsovitz@proxmox.com \
--to=e.huhsovitz@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.