-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathpid.ss
86 lines (75 loc) · 3.42 KB
/
pid.ss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
;;; Copyright (C) 2023-2025 by Massimiliano Ghilardi
;;;
;;; This program is free software; you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 2 of the License, or
;;; (at your option) any later version.
(library (schemesh posix pid (0 8 1))
(export pid-get pgid-get pid-kill pid-wait)
(import
(rnrs)
(only (chezscheme) foreign-procedure)
(only (schemesh bootstrap) assert*)
(only (schemesh posix fd) raise-c-errno)
(only (schemesh posix signal) signal-name->number))
;; (pid-get) returns pid of current process
(define pid-get
(let ((c-pid-get (foreign-procedure "c_pid_get" () int)))
(lambda ()
(let ((ret (c-pid-get)))
(when (< ret 0)
(raise-c-errno 'pid-get 'getpid ret))
ret))))
;; (pgid-get) returns process group of specified process (0 = current process)
(define pgid-get
(let ((c-pgid-get (foreign-procedure "c_pgid_get" (int) int)))
(lambda (pid)
(let ((ret (c-pgid-get pid)))
(when (< ret 0)
(raise-c-errno 'pgid-get 'getpgid ret pid))
ret))))
;; (pid-kill pid signal-name-or-number) calls C function kill(pid, sig)
;; i.e. sends specified signal to the process(es) identified by pid.
;; Notes:
;; pid == 0 means "all processes in the same process group as the caller".
;; pid == -1 means "all processes".
;; pid < -1 means "all processes in process group -pid"
;
;; Returns 0 on success.
;; Otherwise < 0 if signal-name is unknown, or if C function kill() fails with C errno != 0.
(define pid-kill
(let ((c-pid-kill (foreign-procedure "c_pid_kill" (int int int) int))
(c-errno-einval ((foreign-procedure "c_errno_einval" () int))))
(case-lambda
((pid signal-name-or-number pause-if-successful?)
;; (format #t "pid-kill ~s ~s" pid signal-name)
(let ((signal-number (if (fixnum? signal-name-or-number)
signal-name-or-number
(signal-name->number signal-name-or-number))))
(if (fixnum? signal-number)
(c-pid-kill pid signal-number (if pause-if-successful? 1 0))
c-errno-einval)))
((pid signal-name-or-number)
(pid-kill pid signal-name-or-number #f)))))
;; (pid-wait pid may-block) calls waitpid(pid, WUNTRACED) i.e. checks if process specified by pid finished or stopped.
;;
;; Special cases:
;; pid == 0 means "any child process in the same process group as the caller"
;; pid == -1 means "any child process"
;; pid < -1 means "any child process in process group -pid"
;
;; Argument may-block must be either 'blocking or 'nonblocking.
;; If may-block is 'blocking, wait until pid (or any child process, if pid == -1)
;; exits or stops, otherwise check for such conditions without blocking.
;
;; If waitpid() fails with C errno != 0, return < 0.
;; If no child process matches pid, or if may_block is 'nonblocking and no child finished or
;; stopped, return '().
;; Otherwise return a Scheme cons (pid . exit_flag), where exit_flag is one of:
;; process_exit_status, or 256 + signal, or 512 + stop_signal, or 768 if job continued.
(define pid-wait
(let ((c-pid-wait (foreign-procedure "c_pid_wait" (int int) ptr)))
(lambda (pid may-block)
(assert* 'pid-wait (memq may-block '(blocking nonblocking)))
(c-pid-wait pid (if (eq? may-block 'blocking) 1 0)))))
) ; close library