shutdown-manager 1.0.1
Safe and flexible shutdown manager for threads, processes, and asyncio tasks
Requires Python: >=3.8

# Shutdown Manager

[![PyPI Version](https://img.shields.io/pypi/v/shutdown-manager)](https://pypi.org/project/shutdown-manager/)
[![Python Version](https://img.shields.io/pypi/pyversions/shutdown-manager)](https://pypi.org/project/shutdown-manager/)
[![License](https://img.shields.io/pypi/l/shutdown-manager)](https://opensource.org/licenses/MIT)

**Python library for safe, cooperative, and hybrid shutdown of threads, processes, and asyncio tasks.**

---

## Table of Contents

- [Overview](#overview)
- [Installation](#installation)
- [Public API](#public-api)
- [Shutdown Modes](#shutdown-modes)
- [Shutdown Flow Diagram](#shutdown-flow-diagram)
- [Example Usage](#example-usage)
- [Best Practices](#best-practices)
- [License](#license)

---

## Overview

`shutdown-manager` provides a unified way to manage shutdowns in Python:

- Threads  
- Subprocesses  
- Asyncio tasks  
- Signal handling (Ctrl+C)  

Supports three shutdown modes:

1. **Option A (default)** – Cooperative and safe  
2. **Option B (force)** – Immediate and dangerous  
3. **Option C (hybrid)** – Graceful → Force escalation  

---

## Installation

```bash
pip install shutdown-manager

Public API
ShutdownManager

The main orchestrator for threads, subprocesses, and asyncio tasks.

Initialization:

```python
from shutdown_manager import ShutdownManager
import asyncio

manager = ShutdownManager(loop=asyncio.get_event_loop())
```


Key Methods:
```
register_thread(thread: threading.Thread)
register_process(process: subprocess.Popen)
register_async_task(task: asyncio.Task)
shutdown(force: bool = False, timeout: Optional[float] = None)
reset()
state  # Access shared ShutdownState instance
```

Example: Basic Usage

```python
import threading
import asyncio
import subprocess
from shutdown_manager import ShutdownManager

manager = ShutdownManager()

# Thread
def worker(stop_event):
    while not stop_event.is_set():
        print("Thread running")
        import time; time.sleep(1)

t = threading.Thread(target=worker, args=(manager.state.stop_event,))
t.start()
manager.register_thread(t)

# Subprocess
proc = subprocess.Popen(["sleep", "10"])
manager.register_process(proc)

# Async task
async def async_worker(stop_event):
    while not stop_event.is_set():
        await asyncio.sleep(1)

task = asyncio.create_task(async_worker(manager.state.stop_event))
manager.register_async_task(task)

# Cooperative shutdown (Option A)
manager.shutdown()
```

Other Managers

ThreadManager Methods:
```
register(thread)
register_many(threads)
shutdown(force=False, timeout=None)
alive_threads()
clear()
```

ProcessManager Methods:
```
register(process)
register_many(processes)
shutdown(force=False, timeout=None)
alive_processes()
clear()
```

AsyncTaskManager Methods:
```
register(task)
register_many(tasks)
shutdown(force=False, timeout=None)
alive_tasks()
clear()
```

ShutdownState Methods & Attributes:
```
stop_event      # Thread-safe event
is_shutdown     # Boolean flag

trigger_shutdown()
reset()
should_stop()
```

SignalController
Automatically integrates OS signals (Ctrl+C) and triggers manager.shutdown() safely.

Shutdown Modes
Option	Behavior
A (default)	Cooperative: waits for threads, processes, and async tasks to finish naturally. Safe for libraries.
B (force)	Immediate shutdown: interrupts threads, processes, and async tasks. Dangerous.
C (hybrid)	Cooperative shutdown with timeout: waits up to the timeout, then forcefully terminates remaining tasks/processes/threads.
Shutdown Flow Diagram
```
                         ┌────────────────────────┐
                         │   User calls shutdown  │
                         │    (manager.shutdown)  │
                         └───────────┬───────────┘
                                     │
                             ┌───────┴─────────┐
                             │ Option selected?│
                             └───────┬─────────┘
                     ┌──────────────┼──────────────┐
                     │              │              │
                     │ Option A     │ Option B     │ Option C
                     │ (default)    │ (force)      │ (hybrid)
                     │              │              │
        ┌────────────┴─────────┐    │              │
        │ Signal stop_event     │    │              │
        │ Cooperative shutdown  │    │              │
        │ Wait for completion   │    │              │
        └────────────┬─────────┘    │              │
                     │                │              │
             ┌───────┴───────┐        │              │
             │ THREADS        │        │              │
             │ join threads   │        │ Skip join    │
             │ check stop_event│       │ Threads may  │
             │                  │      │ still run   │
             └───────┬─────────┘        │              │
                     │                │              │
             ┌───────┴───────┐        │              │
             │ PROCESSES     │        │              │
             │ terminate()   │        │ Kill()      │
             │ wait natural  │        │ immediate   │
             └───────┬───────┘        │              │
                     │                │              │
             ┌───────┴───────┐        │              │
             │ ASYNC TASKS   │        │              │
             │ cancel tasks  │        │ cancel tasks│
             │ await tasks   │        │ no wait     │
             └───────┬───────┘        │              │
                     │                │              │
          ┌──────────┴─────────┐      │              │
          │ Shutdown Complete  │      │              │
          │ All cooperative    │      │              │
          │ tasks finished     │      │              │
          └───────────────────┘      └──────────────┘
                     │
                     ▼
        ┌──────────────────────────┐
        │ Option C escalation?     │
        │ Wait for timeout         │
        │ Force threads/processes  │
        │ Force cancel tasks       │
        └───────────┬─────────────┘
                    │
                    ▼
        ┌──────────────────────────┐
        │ Shutdown Finished        │
        │ All subsystems stopped   │
        │ or forced after timeout │
        └──────────────────────────┘
```
Best Practices

Use stop_event in threads and async tasks for cooperative shutdown.

Use Option B only when necessary (hung subprocesses).

Option C is recommended for production to prevent hanging tasks.

Call reset() for repeated shutdown cycles in the same script.



License

MIT License