# Linux Daemon in Swift


  # Writing a Proper Linux Daemon in Swift with Signal Handling

Creating a production-grade daemon on Linux requires more than just running a program in the background. A correct implementation must detach from the controlling terminal, manage OS signals, maintain lifecycle files, and behave predictably under systemd or other supervisor tools.

This article explains the architecture behind `signal_14.swift`, a fully functional Swift-based Linux daemon. It covers daemonization, signal handling, heartbeat management, and debugging techniques using LLDB.

---

## Key Concepts

## Daemonization

A proper Linux daemon uses the classic **double-fork** strategy with **session detachment**:

- Fork once so the parent exits.
- Execute `setsid()` to detach from the terminal.
- Fork again so the daemon can never reacquire a terminal.
- Redirect `stdin`, `stdout`, and `stderr` to `/dev/null`.

```swift
// Standard double-fork daemonization pattern.
if fork() > 0 { exit(0) }
setsid()
if fork() > 0 { exit(0) }

freopen("/dev/null", "r", stdin)
freopen("/dev/null", "w", stdout)
freopen("/dev/null", "w", stderr)
```

---

## PID Files and Heartbeat Files

Daemons typically maintain two important files:

1. **PID file**: Helps systemd, supervisor, or scripts locate the running process.  
2. **Heartbeat (HB) file**: A simple way to track liveness without watching logs.

`signal_14.swift` writes a timestamp to a heartbeat file every N seconds:

```swift
let hbPath = "/tmp/swift_daemon.hb"

func writeHeartbeat() {
    let ts = "\(Date().timeIntervalSince1970)\n"
    try? ts.write(toFile: hbPath, atomically: true, encoding: .utf8)
}
```

This makes it trivial to monitor:

```bash
watch -n 1 cat /tmp/swift_daemon.hb
```

---

## Signal Handling

A daemon must respond correctly to OS signals. A minimal set includes:

- **SIGTERM**: Trigger graceful shutdown.
- **SIGINT**: Same as SIGTERM when not attached to a terminal.
- **SIGHUP**: Reload configuration.
- **SIGUSR1 / SIGUSR2**: Custom actions.

Swift on Linux uses `sigaction` for signal handling:

```swift
var action = sigaction()
action.__sigaction_handler = unsafeBitCast(handleSignal, to: sigaction.__Unnamed_union___sigaction_handler.self)
sigaction(SIGTERM, &action, nil)
sigaction(SIGINT, &action, nil)
```

The callback:

```swift
func handleSignal(_ sig: Int32) {
    switch sig {
    case SIGTERM, SIGINT:
        shouldRun = false
    case SIGHUP:
        reloadConfig()
    case SIGUSR1:
        rotateLogs()
    default:
        break
    }
}
```

This design ensures the daemon remains responsive and predictable under load or during shutdown.

---

## Main Loop

The daemon's event loop should:

- Run until a termination signal arrives.
- Write a heartbeat periodically.
- Perform business logic without blocking.

```swift
while shouldRun {
    writeHeartbeat()
    sleep(2)
}
```

The loop avoids writing to stdout or stderr because these are redirected to `/dev/null`. Any diagnostic output goes to a log file.

---

## Log File Redirection

A production daemon must not print to the terminal. Instead, create or append logs to a file:

```swift
let logPath = "/tmp/swift_daemon.log"
freopen(logPath, "a+", stdout)
freopen(logPath, "a+", stderr)
```

This ensures logs survive restarts and can be tailed:

```bash
tail -f /tmp/swift_daemon.log
```

---

## Testing the Daemon with LLDB

LLDB makes it possible to debug a running daemon:

### 1. Start daemon normally:

```bash
./signal_14.swift &
```

### 2. Attach LLDB:

```bash
lldb -p $(pidof signal_14.swift)
```

### 3. Inspect state:

```
(lldb) bt
(lldb) frame variable
(lldb) p shouldRun
```

### 4. Detach without killing:

```bash
(lldb) detach
```

LLDB is safe for production-grade debugging because Swift binaries expose rich symbol information.

---

## systemd Integration

Place the following unit file in `/etc/systemd/system/swift-daemon.service`:

```
[Unit]
Description=Swift Linux Daemon

[Service]
ExecStart=/usr/local/bin/signal_14
Restart=always
PIDFile=/tmp/swift_daemon.pid

[Install]
WantedBy=multi-user.target
```

Then enable:

```bash
sudo systemctl daemon-reload
sudo systemctl enable swift-daemon
sudo systemctl start swift-daemon
```

To monitor:

```bash
systemctl status swift-daemon
journalctl -u swift-daemon -f
```

---

## Why Swift Works Well for Daemons

Swift provides:

- Memory safety with zero-cost abstractions.
- Predictable performance.
- Access to the full POSIX API.
- Clean, modern syntax for systems engineering.

This allows you to combine low-level Linux process control with high-level Swift design patterns.

---

## Summary

A production-grade Linux daemon written in Swift requires:

- Double-fork and session detachment.
- PID and heartbeat lifecycle files.
- Robust, POSIX-compliant signal management.
- Background logging to a file.
- A responsive main loop.
- Optional LLDB and systemd integration.

`signal_14.swift` demonstrates that Swift is not just for iOS or server frameworks; it is a capable systems programming language for long-running background processes on Linux.

---


