Skip to content

Commit b70aa87

Browse files
committed
Add possibility to update original sigaction for unsigactioned delaying
1 parent 63c5c95 commit b70aa87

File tree

3 files changed

+34
-11
lines changed

3 files changed

+34
-11
lines changed

Sources/SignalHandling/CStructsInSwift/Sigaction.swift

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,22 +97,30 @@ public struct Sigaction : Equatable, RawRepresentable {
9797

9898
It is impossible for a sigaction handler to be `nil`. If the method returns
9999
`nil`, the previous handler was exactly the same as the one you installed.
100-
Note however the sigaction function is always called in this method. */
100+
Note however the sigaction function is always called in this method.
101+
102+
If `updateUnsigRegistrations` is true (default), If there are delayed
103+
sigactions registered with `SigactionDelayer_Unsig`, these registrations will
104+
be updated and `sigaction` will not be called. */
101105
@discardableResult
102-
public func install(on signal: Signal, revertIfIgnored: Bool = true) throws -> Sigaction? {
106+
public func install(on signal: Signal, revertIfIgnored: Bool = true, updateUnsigRegistrations: Bool = true) throws -> Sigaction? {
107+
if updateUnsigRegistrations, let oldSigaction = SigactionDelayer_Unsig.updateOriginalSigaction(for: signal, to: self) {
108+
return (oldSigaction != self ? oldSigaction : nil)
109+
}
110+
103111
var oldCAction = sigaction()
104112
var newCAction = self.rawValue
105113
guard sigaction(signal.rawValue, &newCAction, &oldCAction) == 0 else {
106114
throw SignalHandlingError.nonDestructiveSystemError(Errno(rawValue: errno))
107115
}
108116
let oldSigaction = Sigaction(rawValue: oldCAction)
109117
if revertIfIgnored && oldSigaction == .ignoreAction {
110-
guard sigaction(signal.rawValue, &newCAction, &oldCAction) == 0 else {
118+
guard sigaction(signal.rawValue, &oldCAction, nil) == 0 else {
111119
throw SignalHandlingError.destructiveSystemError(Errno(rawValue: errno))
112120
}
121+
return nil
113122
}
114-
if oldSigaction != self {return oldSigaction}
115-
else {return nil}
123+
return (oldSigaction != self ? oldSigaction : nil)
116124
}
117125

118126
}

Sources/SignalHandling/DelayedSigaction/SigactionDelayer_Block.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,13 +368,13 @@ public enum SigactionDelayer_Block {
368368
}
369369
sigdelset(&sigset, signal.rawValue)
370370

371-
let oldAction = try Sigaction.ignoreAction.install(on: signal, revertIfIgnored: false)
371+
let oldAction = try Sigaction.ignoreAction.install(on: signal, revertIfIgnored: false, updateUnsigRegistrations: false)
372372
/* Will not hurt, the signal is ignore anyway (yes, there is a
373373
 * race condition, I know). */
374374
pthread_kill(pthread_self(), signal.rawValue)
375375
/* No sigsuspend. Would block because signal is ignored. */
376376
if let oldAction = oldAction {
377-
do {try oldAction.install(on: signal, revertIfIgnored: false)}
377+
do {try oldAction.install(on: signal, revertIfIgnored: false, updateUnsigRegistrations: false)}
378378
catch let error as SignalHandlingError {
379379
throw error.upgradeToDestructive()
380380
}

Sources/SignalHandling/DelayedSigaction/SigactionDelayer_Unsig.swift

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,21 @@ public enum SigactionDelayer_Unsig {
6464
}
6565
}
6666

67+
/**
68+
Change the original sigaction of the given signal if it was registered for an
69+
unsigaction. This is useful if you want to change the sigaction handler after
70+
having registered an unsigaction.
71+
72+
Returns the previous sigaction if there was an unsigaction registered for the
73+
given signal, `nil` otherwise. */
74+
public static func updateOriginalSigaction(for signal: Signal, to sigaction: Sigaction) -> Sigaction? {
75+
return signalProcessingQueue.sync{
76+
let previous = unsigactionedSignals[signal]?.originalSigaction
77+
unsigactionedSignals[signal]?.originalSigaction = sigaction
78+
return previous
79+
}
80+
}
81+
6782
/* ***************
6883
   MARK: - Private
6984
   *************** */
@@ -150,7 +165,7 @@ public enum SigactionDelayer_Unsig {
150165
private static func registerDelayedSigactionOnQueue(_ signal: Signal, handler: @escaping DelayedSigactionHandler) throws -> DelayedSigaction {
151166
/* Whether the signal was retained before or not, we re-install the ignore
152167
 * handler on the given signal. */
153-
let oldSigaction = try Sigaction.ignoreAction.install(on: signal, revertIfIgnored: false)
168+
let oldSigaction = try Sigaction.ignoreAction.install(on: signal, revertIfIgnored: false, updateUnsigRegistrations: false)
154169

155170
let delayedSigaction = DelayedSigaction(signal: signal)
156171

@@ -212,7 +227,7 @@ public enum SigactionDelayer_Unsig {
212227

213228
/* Now we have removed **all** unsigactions on the given signal. Let’s
214229
 * restore the signal to the state before unsigactions. */
215-
try unsigactionedSignal.originalSigaction.install(on: id.signal, revertIfIgnored: false)
230+
try unsigactionedSignal.originalSigaction.install(on: id.signal, revertIfIgnored: false, updateUnsigRegistrations: false)
216231
unsigactionedSignal.dispatchSource.cancel()
217232

218233
/* Finally, once the sigaction has been restored to the original value, we
@@ -315,7 +330,7 @@ public enum SigactionDelayer_Unsig {
315330
/* Install the original sigaction temporarily. In case of
316331
 * failure we do not even send the signal to ourselves, it’d
317332
 * be useless. */
318-
let previousSigaction = try sigaction.install(on: signal, revertIfIgnored: false)
333+
let previousSigaction = try sigaction.install(on: signal, revertIfIgnored: false, updateUnsigRegistrations: false)
319334

320335
/* We send the signal to the thread directly. libdispatch uses
321336
 * kqueue (on BSD, signalfd on Linux) and thus signals sent to
@@ -352,7 +367,7 @@ public enum SigactionDelayer_Unsig {
352367
 * This is the only way I can think of. */
353368
// sleep(3)
354369
if let previousSigaction = previousSigaction {
355-
do {try previousSigaction.install(on: signal, revertIfIgnored: false)}
370+
do {try previousSigaction.install(on: signal, revertIfIgnored: false, updateUnsigRegistrations: false)}
356371
catch let error as SignalHandlingError {
357372
throw error.upgradeToDestructive()
358373
}

0 commit comments

Comments
 (0)