Linux Daemon in Swift

Search for a command to run...

No comments yet. Be the first to comment.
Modern software systems often separate control logic from high-performance execution logic. This design is common in networking, distributed systems, operating systems, storage engines, and embedded s

Introduction Engineering software often combines multiple programming languages to leverage their individual strengths. A common approach is to implement computational algorithms in native C or C++ wh

Deadlocks are one of the most common synchronization problems encountered in operating systems and concurrent programming. Although the concept is frequently introduced in textbooks, observing it insi

Memory and resource allocation are fundamental operations inside the Linux kernel. Whether assigning device IDs, managing CPU masks, allocating interrupt vectors, or tracking hardware resources, the k

The Linux scheduler is one of the most important components of the operating system. Every running program, background service, and kernel thread eventually interacts with the scheduler. In this artic

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.
A proper Linux daemon uses the classic double-fork strategy with session detachment:
setsid() to detach from the terminal.stdin, stdout, and stderr to /dev/null.// 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)
Daemons typically maintain two important files:
signal_14.swift writes a timestamp to a heartbeat file every N seconds:
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:
watch -n 1 cat /tmp/swift_daemon.hb
A daemon must respond correctly to OS signals. A minimal set includes:
Swift on Linux uses sigaction for signal handling:
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:
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.
The daemon's event loop should:
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.
A production daemon must not print to the terminal. Instead, create or append logs to a file:
let logPath = "/tmp/swift_daemon.log"
freopen(logPath, "a+", stdout)
freopen(logPath, "a+", stderr)
This ensures logs survive restarts and can be tailed:
tail -f /tmp/swift_daemon.log
LLDB makes it possible to debug a running daemon:
./signal_14.swift &
lldb -p $(pidof signal_14.swift)
(lldb) bt
(lldb) frame variable
(lldb) p shouldRun
(lldb) detach
LLDB is safe for production-grade debugging because Swift binaries expose rich symbol information.
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:
sudo systemctl daemon-reload
sudo systemctl enable swift-daemon
sudo systemctl start swift-daemon
To monitor:
systemctl status swift-daemon
journalctl -u swift-daemon -f
Swift provides:
This allows you to combine low-level Linux process control with high-level Swift design patterns.
A production-grade Linux daemon written in Swift requires:
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.