Skip to content

Commit 8e69446

Browse files
committed
impr(Lib/signal): use AC_CHECK_FUNCS
1 parent d26c786 commit 8e69446

File tree

5 files changed

+94
-64
lines changed

5 files changed

+94
-64
lines changed

src/pylib/Lib/n_signal.nim

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ let NSIG* = int Py_NSIG
88
export signals, signal_util, enums
99
export SIG_DFL, SIG_IGN
1010

11-
when defined(unix):
12-
import ./signal_impl/unixs
13-
export unixs
11+
import ./signal_impl/unixs
12+
export unixs
1413

1514
proc valid_signals*(): HashSet[int] =
1615
result = initHashSet[int]()

src/pylib/Lib/signal.nim

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,16 @@ import ../version
1010
import ./collections/abc
1111

1212
export n_signal except sigpending, pthread_sigmask, strsignal, valid_signals
13-
when defined(unix):
14-
proc sigpending*(): PySet[int] = newPySet n_signal.sigpending()
1513

16-
proc pthread_sigmask*(how: int, mask: Sigset): PySet[int] =
17-
newPySet n_signal.pthread_sigmask(how, mask)
14+
import std/macros
15+
macro mayUndef(def) =
16+
let cond = newCall("declared", def.name)
17+
result = nnkWhenStmt.newTree(nnkElifBranch.newTree(cond, def))
18+
19+
proc sigpending*(): PySet[int]{.mayUndef.} = newPySet n_signal.sigpending()
20+
21+
proc pthread_sigmask*(how: int, mask: Sigset): PySet[int]{.mayUndef.} =
22+
newPySet n_signal.pthread_sigmask(how, mask)
1823

1924
#[ XXX: NIM-BUG: compiler stuck here
2025
converter toSigset*(oa: Iterable[int]): Sigset =

src/pylib/Lib/signal_impl/unixs.nim

Lines changed: 67 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
import std/sets
3-
3+
import std/macros
44
import ./[
55
errutil,
66
c_api,
@@ -11,31 +11,42 @@ import ./[
1111
siginfo_decl
1212
]
1313
import ../sys_impl/auditImpl as sys
14-
export Sigset
14+
when HAVE_SIGSET_T:
15+
export Sigset
16+
converter toSigset*(oa: openArray[int]): Sigset = result.fromIterable oa
17+
1518
export siginfo_decl except fill_siginfo
1619
import ../../Python/pytime/[deadline, pytimeFromSeconds, pytimeAsTimeval]
1720

18-
proc alarm*(seconds: int): int = int alarm seconds.cint
19-
proc pause*(): int = int posix.pause()
20-
21-
proc pthread_kill*(thread_id: uint, signalnum: int) =
22-
sys.audit("signal.pthread_kill", thread_id, signalnum)
23-
let err = pthread_kill(Pthread thread_id, cint signalnum)
24-
if err != 0:
25-
raiseErrno()
21+
proc mayUndefImpl(def: NimNode): NimNode =
22+
let cond = ident "HAVE_" & def.name.strVal
23+
result = nnkWhenStmt.newTree(nnkElifBranch.newTree(cond, def))
24+
macro mayUndef(def) = mayUndefImpl(def)
25+
macro mayUndefs(defs) =
26+
result = newStmtList()
27+
for def in defs:
28+
result.add mayUndefimpl(def)
29+
30+
mayUndefs:
31+
proc alarm*(seconds: int): int = int alarm seconds.cint
32+
proc pause*(): int = int posix.pause()
33+
34+
proc pthread_kill*(thread_id: uint, signalnum: int) =
35+
sys.audit("signal.pthread_kill", thread_id, signalnum)
36+
let err = pthread_kill(Pthread thread_id, cint signalnum)
37+
if err != 0:
38+
raiseErrno()
2639

27-
PyErr_CheckSignalsAndRaises()
40+
PyErr_CheckSignalsAndRaises()
2841

2942
type
3043
Set[T] = HashSet[T]
3144

32-
converter toSigset*(oa: openArray[int]): Sigset = result.fromIterable oa
33-
3445

3546
template markVar(sym) =
3647
var sym = sym
3748

38-
proc pthread_sigmask*(how: int, mask: Sigset): Set[int] =
49+
proc pthread_sigmask*(how: int, mask: Sigset): Set[int]{.mayUndef.} =
3950
var previous: Sigset
4051
markVar mask
4152
let err = pthread_sigmask(how.cint, mask, previous)
@@ -44,44 +55,48 @@ proc pthread_sigmask*(how: int, mask: Sigset): Set[int] =
4455
PyErr_CheckSignalsAndRaises()
4556
sigset_to_set(previous)
4657

47-
type ItimerVal*{.importc: "struct itimerval", header: "<sys/time.h>".} = object
48-
it_interval, it_value: Timeval
49-
type ItimerWhich = cint # enum
50-
proc setitimer(which: ItimerWhich, `new`, old: ItimerVal): cint {.importc, header: "<sys/header.h>".}
51-
proc getitimer(which: ItimerWhich, old: ItimerVal): cint {.importc, header: "<sys/header.h>".}
52-
53-
func toFloat(tv: Timeval): float =
54-
tv.tv_sec.float + tv.tv_usec.float / 1_000_000.0
55-
56-
proc itimer_retval(old: ItimerVal): tuple[delay, interval: float] =
57-
(old.it_value.toFloat, old.it_interval.toFloat)
58-
59-
proc toTimeval(obj: float): Timeval =
60-
## timeval_from_double
61-
var t: PyTime
62-
t.fromSecondsObject(obj, prCeiling)
63-
t.asTimeval(prCeiling)
64-
6558
type ItimerError* = object of PyOSError
6659

67-
proc setitimer*(which: int, seconds: float; interval=0.0): tuple[delay, interval: float] =
68-
var n: ItimerVal
69-
n.it_value = seconds.toTimeval
70-
n.it_interval = interval.toTimeval
71-
var old: ItimerVal
72-
if setitimer(which.cint, n, old) != 0:
73-
raiseErrnoT[ItimerError]()
74-
itimer_retval old
75-
76-
proc getitimer*(which: int): tuple[delay, interval: float] =
77-
var old: ItimerVal
78-
if getitimer(which.cint, old) != 0:
79-
raiseErrnoT[ItimerError]()
80-
81-
itimer_retval old
60+
when HAVE_SETITIMER or HAVE_GETITIMER:
61+
type ItimerVal*{.importc: "struct itimerval", header: "<sys/time.h>".} = object
62+
it_interval, it_value: Timeval
63+
type ItimerWhich = cint # enum
64+
func toFloat(tv: Timeval): float =
65+
tv.tv_sec.float + tv.tv_usec.float / 1_000_000.0
66+
67+
proc itimer_retval(old: ItimerVal): tuple[delay, interval: float] =
68+
(old.it_value.toFloat, old.it_interval.toFloat)
69+
70+
71+
when HAVE_SETITIMER:
72+
proc setitimer(which: ItimerWhich, `new`, old: ItimerVal): cint {.importc, header: "<sys/header.h>".}
73+
proc toTimeval(obj: float): Timeval =
74+
## timeval_from_double
75+
var t: PyTime
76+
t.fromSecondsObject(obj, prCeiling)
77+
t.asTimeval(prCeiling)
78+
79+
80+
proc setitimer*(which: int, seconds: float; interval=0.0): tuple[delay, interval: float] =
81+
var n: ItimerVal
82+
n.it_value = seconds.toTimeval
83+
n.it_interval = interval.toTimeval
84+
var old: ItimerVal
85+
if setitimer(which.cint, n, old) != 0:
86+
raiseErrnoT[ItimerError]()
87+
itimer_retval old
88+
89+
when HAVE_GETITIMER:
90+
proc getitimer(which: ItimerWhich, old: ItimerVal): cint {.importc, header: "<sys/header.h>".}
91+
proc getitimer*(which: int): tuple[delay, interval: float] =
92+
var old: ItimerVal
93+
if getitimer(which.cint, old) != 0:
94+
raiseErrnoT[ItimerError]()
95+
96+
itimer_retval old
8297
8398
84-
proc siginterrupt*(signalnum, flag: int) =
99+
proc siginterrupt*(signalnum, flag: int){.mayUndef.} =
85100
let csignalnum = cint signalnum
86101
csignalnum.chkSigRng
87102
when HAVE_SIGACTION:
@@ -98,20 +113,20 @@ proc siginterrupt*(signalnum, flag: int) =
98113
raiseErrno()
99114
100115
101-
proc sigpending*(): Set[int] =
116+
proc sigpending*(): Set[int]{.mayUndef.} =
102117
var mask: Sigset
103118
if 0 != sigpending(mask):
104119
raiseErrno()
105120
sigset_to_set mask
106121
107-
proc sigwait*(sigset: Sigset): int =
122+
proc sigwait*(sigset: Sigset): int{.mayUndef.} =
108123
var signum: cint
109124
markVar sigset
110125
let err = sigwait(sigset, signum)
111126
if err != 0:
112127
raiseErrno err
113128
114-
proc sigwaitinfo*(sigset: Sigset): struct_siginfo =
129+
proc sigwaitinfo*(sigset: Sigset): struct_siginfo{.mayUndef.} =
115130
var err: cint
116131
var si: SigInfo
117132
var async_err = 0
@@ -132,7 +147,7 @@ proc sigwaitinfo*(sigset: Sigset): struct_siginfo =
132147
proc PyTime_AsTimespec(x: TimeStamp): Timespec =
133148
x.nPyTime_ObjectToTimeval(result.tv_sec, result.tv_usec, prCeiling)
134149
135-
proc sigtimedwait*(sigset: Sigset, timeout: TimeStamp): struct_siginfo =
150+
proc sigtimedwait*(sigset: Sigset, timeout: TimeStamp): struct_siginfo{.mayUndef.} =
136151
var si: SigInfo
137152
markVar sigset
138153
var to: PyTime

src/pylib/Python/pylifecycle/signal/c_syms.nim

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11

2+
import ../../../pyconfig/signal
3+
export signal
4+
const
5+
HAVE_BROKEN_PTHREAD_SIGMASK* = defined(cygwin) # XXX: cygwin not supported
6+
PYPTHREAD_SIGMASK* = HAVE_PTHREAD_SIGMASK and not HAVE_BROKEN_PTHREAD_SIGMASK
7+
HAVE_SIGSET_T* = PYPTHREAD_SIGMASK or HAVE_SIGWAIT or
8+
HAVE_SIGWAITINFO or HAVE_SIGTIMEDWAIT
9+
210
when defined(windows):
311
import std/winlean
412
export winlean
@@ -21,7 +29,7 @@ else:
2129

2230
import ./handler_types
2331

24-
const HAVE_SIGACTION* = declared(sigaction)
32+
2533
when HAVE_SIGACTION:
2634
proc sigaction*(a1: cint; a2: ptr Sigaction; a3: var Sigaction): cint{.importc: "sigaction", header: "<sys/signal.h>".}
2735
## XXX: posix/winlean's a2 cannot be nil (a var Sigaction)

src/pylib/pyconfig/signal.nim

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@ const Py_NSIG* = from_c_int(Py_NSIG, 64):
2525
#endif
2626
""".}
2727

28-
AC_LINK_IFELSE HAVE_STRSIGNAL, false:
29-
proc strsignal(signalnum: cint): cstring {.importc, header: "<string.h>".}
30-
discard strsignal(0)
31-
28+
AC_CHECK_FUNCS(strsignal, pthread_kill, alarm, pause,
29+
getitimer,
30+
setitimer,
31+
sigaction, #sigaltstack \
32+
sigfillset, siginterrupt, sigpending, #[sigrelse,]# sigtimedwait, sigwait,
33+
sigwaitinfo)
34+
AC_CHECK_FUNC(pthread_sigmask)
3235
const DEF_SIG* = -1 ## CPython checks `SIG*` in [0, NSIG)
3336
when not defined(windows):
3437
template SIG(sym) =

0 commit comments

Comments
 (0)