@@ -35,13 +35,50 @@ import (
3535 "github.com/containerd/nerdctl/v2/pkg/rootlessutil"
3636)
3737
38+ // IsDbusFunctional tests if DBUS connections actually work in the current environment.
39+ // This is more reliable than just checking if DBUS tools are installed.
40+ func IsDbusFunctional (ctx context.Context ) bool {
41+ // Create timeout context to prevent hanging on DBUS connection attempts
42+ timeoutCtx , cancel := context .WithTimeout (ctx , 2 * time .Second )
43+ defer cancel ()
44+
45+ var conn * dbus.Conn
46+ var err error
47+
48+ if rootlessutil .IsRootless () {
49+ // Test user DBUS connection for rootless environments
50+ conn , err = dbus .NewUserConnectionContext (timeoutCtx )
51+ } else {
52+ // Test system DBUS connection for rootful environments
53+ conn , err = dbus .NewSystemConnectionContext (timeoutCtx )
54+ }
55+
56+ if err != nil {
57+ return false
58+ }
59+ defer conn .Close ()
60+ return true
61+ }
62+
3863// CreateTimer sets up the transient systemd timer and service for healthchecks.
3964func CreateTimer (ctx context.Context , container containerd.Container ) error {
4065 hc := extractHealthcheck (ctx , container )
4166 if hc == nil {
67+ log .G (ctx ).Debugf ("No healthcheck configuration found for container %s" , container .ID ())
4268 return nil
4369 }
44- if shouldSkipHealthCheckSystemd (hc ) {
70+
71+ if shouldSkipHealthCheckSystemd (ctx , hc ) {
72+ // Log specific reason for skipping to help with troubleshooting
73+ if ! defaults .IsSystemdAvailable () {
74+ log .G (ctx ).Infof ("Skipping healthcheck timer for container %s: systemd not available" , container .ID ())
75+ } else if ! IsDbusFunctional (ctx ) {
76+ log .G (ctx ).Infof ("Skipping healthcheck timer for container %s: DBUS connection unavailable (likely containerized environment)" , container .ID ())
77+ } else if os .Getenv ("DISABLE_HC_SYSTEMD" ) == "true" {
78+ log .G (ctx ).Infof ("Skipping healthcheck timer for container %s: disabled by DISABLE_HC_SYSTEMD" , container .ID ())
79+ } else if hc == nil || len (hc .Test ) == 0 || hc .Test [0 ] == "NONE" || hc .Interval == 0 {
80+ log .G (ctx ).Debugf ("Skipping healthcheck timer for container %s: invalid healthcheck configuration" , container .ID ())
81+ }
4582 return nil
4683 }
4784
@@ -91,7 +128,7 @@ func StartTimer(ctx context.Context, container containerd.Container) error {
91128 log .G (ctx ).Infof ("DEBUG: No healthcheck found, skipping StartTimer" )
92129 return nil
93130 }
94- if shouldSkipHealthCheckSystemd (hc ) {
131+ if shouldSkipHealthCheckSystemd (ctx , hc ) {
95132 log .G (ctx ).Infof ("DEBUG: Skipping healthcheck systemd, shouldSkip=true" )
96133 return nil
97134 }
@@ -291,16 +328,16 @@ func extractHealthcheck(ctx context.Context, container containerd.Container) *He
291328}
292329
293330// shouldSkipHealthCheckSystemd determines if healthcheck timers should be skipped.
294- func shouldSkipHealthCheckSystemd (hc * Healthcheck ) bool {
331+ func shouldSkipHealthCheckSystemd (ctx context. Context , hc * Healthcheck ) bool {
295332 // Don't proceed if systemd is unavailable or disabled
296333 if ! defaults .IsSystemdAvailable () || os .Getenv ("DISABLE_HC_SYSTEMD" ) == "true" {
297334 return true
298335 }
299336
300- // Skip healthchecks in environments without dbus-launch to avoid permission issues
301- // if _, err := exec.LookPath("dbus-launch"); err != nil {
302- // return true
303- // }
337+ // Test actual DBUS connectivity - this is more reliable than checking for tools
338+ if ! IsDbusFunctional ( ctx ) {
339+ return true
340+ }
304341
305342 // Don't proceed if health check is nil, empty, explicitly NONE or interval is 0.
306343 if hc == nil || len (hc .Test ) == 0 || hc .Test [0 ] == "NONE" || hc .Interval == 0 {
0 commit comments