Skip to content

Bug: ApplicationResourceMonitor.shutdown() doesn't wait for scheduler termination #235

@sfloess

Description

@sfloess

Description

ApplicationResourceMonitor.shutdown() calls scheduler.shutdown() but doesn't wait for the scheduler to actually terminate, inconsistent with shutdown patterns used elsewhere in the codebase.

Location

jplatform-monitoring/src/main/java/org/flossware/jplatform/monitoring/ApplicationResourceMonitor.java:380-383

Current Code

public void shutdown() {
    logger.info("[{}] Shutting down resource monitor", applicationId);
    scheduler.shutdown();
    // Doesn't wait! Returns immediately
}

Problem

ApplicationResourceMonitor monitor = new ApplicationResourceMonitor("app1", threadGroup);

// Later:
monitor.shutdown();
// Returns immediately, but scheduler may still be running!

// If application undeploys immediately after:
applicationManager.undeploy("app1");
// The collectMetrics() task might still be executing
// Accessing threadGroup, quota, etc. that are being cleaned up

Impact

  • Race condition: shutdown may return while background task still running
  • Background task may access application resources during cleanup
  • Inconsistent with other shutdown methods in codebase (ManagedThreadPool, SwingConsole, etc.)
  • No way to ensure clean shutdown

Comparison with Other Classes

ManagedThreadPool.shutdown() (lines 165-179):

executor.shutdown();
try {
    if (!executor.awaitTermination(shutdownTimeoutSeconds, TimeUnit.SECONDS)) {
        executor.shutdownNow();
    }
} catch (InterruptedException e) {
    executor.shutdownNow();
    Thread.currentThread().interrupt();
}

SwingConsole.shutdown() (lines 378-392):

refreshExecutor.shutdown();
try {
    if (!refreshExecutor.awaitTermination(2, TimeUnit.SECONDS)) {
        refreshExecutor.shutdownNow();
    }
} catch (InterruptedException e) {
    refreshExecutor.shutdownNow();
    Thread.currentThread().interrupt();
}

Fix

public void shutdown() {
    logger.info("[{}] Shutting down resource monitor", applicationId);
    scheduler.shutdown();
    
    try {
        if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
            logger.warn("[{}] Resource monitor did not terminate in 5 seconds, forcing shutdown",
                       applicationId);
            scheduler.shutdownNow();
            
            // Wait a bit longer for shutdownNow() to take effect
            if (!scheduler.awaitTermination(2, TimeUnit.SECONDS)) {
                logger.error("[{}] Resource monitor failed to terminate", applicationId);
            }
        }
    } catch (InterruptedException e) {
        logger.warn("[{}] Interrupted while waiting for resource monitor shutdown", applicationId);
        scheduler.shutdownNow();
        Thread.currentThread().interrupt();
    }
    
    logger.info("[{}] Resource monitor shut down", applicationId);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions