Contents:

1. Introduction

This module contains all the common code for "daemon" programs (eg. servers etc.) to be run on the Linux operating system. (All this is very likely to work on all Unix systems, though it has been tested on Linux only.)

2. Overview

Overview

if not port? system/ports/system [
 system/ports/system: open system://
]
handler!: context [
 title: "Daemon"
 logging: [all to output]
 on-init: none
 on-wakeup: none
 on-quit: none
 on-child-termination: none
 pid-file: none
 wait-loop: none
]
start-daemon: func [
 "Handle signals and basic daemon functionality"
 handlers [block! object!] "Handler functions and other settings"
] [
 if block? handlers [handlers: make handler! handlers]
 set-modes system/ports/system [
  signal: [SIGINT SIGTERM SIGUSR1 SIGQUIT]
 ]
 setup-logging handlers/logging
 append-log 'info [handlers/title "starting up..."]
 system/ports/system/awake: func [port /local result message pid] [
  result: false
  while [message: pick port 1] [
   parse message [
    'signal [
     'SIGUSR1 (
      append-log 'info ["Received SIGUSR1. Process is alive."]
      handlers/on-wakeup
     )
     |
     'SIGINT (
      append-log 'info ["Received SIGINT. Quitting."]
      quit
     )
     |
     ['SIGTERM | 'SIGQUIT] (
      append-log 'info ["Received " uppercase form message/2 ". Quitting nicely."]
      handlers/on-quit
      if handlers/pid-file [delete handlers/pid-file]
      result: true
     )
    ]
    |
    'child set pid integer! integer! (
     handlers/on-child-termination pid
    )
   ]
  ]
  result
 ]
 if file? handlers/pid-file [
  save handlers/pid-file first load/next %/proc/self/stat
 ]
 handlers/on-init
 either get in handlers 'wait-loop [
  insert tail system/ports/wait-list system/ports/system
  handlers/wait-loop
 ] [
  ; workaround for CHILD messages not waking up the system port
  forever [
   if port? wait [system/ports/system 10] [exit]
   system/ports/system/awake system/ports/system
  ]
 ]
]