| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent cc1e55e commit 0dfc93a
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5053,13 +5053,11 @@ def alarm2(sig, frame): | |||
| 5053 | 5053 | if e.errno != errno.EBADF: | |
| 5054 | 5054 | raise | |
| 5055 | 5055 | ||
| 5056 | - @unittest.skip("TODO: RUSTPYTHON; thread 'main' (103833) panicked at crates/vm/src/stdlib/signal.rs:233:43: RefCell already borrowed") | ||
| 5057 | 5056 | @requires_alarm | |
| 5058 | 5057 | @support.requires_resource('walltime') | |
| 5059 | 5058 | def test_interrupted_write_retry_buffered(self): | |
| 5060 | 5059 | self.check_interrupted_write_retry(b"x", mode="wb") | |
| 5061 | 5060 | ||
| 5062 | - @unittest.skip("TODO: RUSTPYTHON; thread 'main' (103833) panicked at crates/vm/src/stdlib/signal.rs:233:43: RefCell already borrowed") | ||
| 5063 | 5061 | @requires_alarm | |
| 5064 | 5062 | @support.requires_resource('walltime') | |
| 5065 | 5063 | def test_interrupted_write_retry_text(self): | |
@@ -5069,10 +5067,6 @@ def test_interrupted_write_retry_text(self): | |||
| 5069 | 5067 | class CSignalsTest(SignalsTest): | |
| 5070 | 5068 | io = io | |
| 5071 | 5069 | ||
| 5072 | - @unittest.skip("TODO: RUSTPYTHON; thread 'main' (103833) panicked at crates/vm/src/stdlib/signal.rs:233:43: RefCell already borrowed") | ||
| 5073 | - def test_interrupted_read_retry_buffered(self): | ||
| 5074 | - return super().test_interrupted_read_retry_buffered() | ||
| 5075 | - | ||
| 5076 | 5070 | class PySignalsTest(SignalsTest): | |
| 5077 | 5071 | io = pyio | |
| 5078 | 5072 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -88,17 +88,23 @@ fn trigger_signals(vm: &VirtualMachine) -> PyResult<()> { | |||
| 88 | 88 | let signal_handlers = vm | |
| 89 | 89 | .signal_handlers | |
| 90 | 90 | .get() | |
| 91 | - .expect("should never fail since we check above") | ||
| 92 | - .borrow(); | ||
| 91 | + .expect("should never fail since we check above"); | ||
| 93 | 92 | ||
| 94 | 93 | for (signum, trigger) in TRIGGERS.iter().enumerate().skip(1) { | |
| 95 | 94 | let triggered = trigger.swap(false, Ordering::Relaxed); | |
| 95 | + if !triggered { | ||
| 96 | + continue; | ||
| 97 | + } | ||
| 96 | 98 | ||
| 97 | 99 | // SAFETY: TRIGGERS has the same length as the signal_handlers | |
| 98 | 100 | let signum = unsafe { SignalNum::new_unchecked(signum as i32) }; | |
| 99 | 101 | ||
| 100 | - if triggered | ||
| 101 | - && let Some(handler) = &signal_handlers[signum] | ||
| 102 | + // Read the handler out and drop the borrow before running it. A | ||
| 103 | + // handler is free to call signal.signal(), which takes the same cell | ||
| 104 | + // mutably, and a live read borrow turns that into a panic. | ||
| 105 | + let handler = signal_handlers.borrow()[signum].clone(); | ||
| 106 | + | ||
| 107 | + if let Some(handler) = handler | ||
| 102 | 108 | && let Some(callable) = handler.to_callable() | |
| 103 | 109 | { | |
| 104 | 110 | callable.invoke((signum.as_i32(), vm.ctx.none()), vm)?; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -41,3 +41,39 @@ def handler(signum, frame): | |||
| 41 | 41 | time.sleep(2.0) | |
| 42 | 42 | ||
| 43 | 43 | assert signals == [signal.SIGALRM, signal.SIGALRM] | |
| 44 | + | ||
| 45 | + # A handler may call signal.signal(), and the usual reason is to disarm | ||
| 46 | + # itself. Reading the handler table while the handler runs used to be a | ||
| 47 | + # crash rather than a rearm. | ||
| 48 | + rearmed = [] | ||
| 49 | + | ||
| 50 | + def rearm(signum, frame): | ||
| 51 | + rearmed.append(signum) | ||
| 52 | + signal.signal(signal.SIGALRM, signal.SIG_IGN) | ||
| 53 | + | ||
| 54 | + signal.signal(signal.SIGALRM, rearm) | ||
| 55 | + signal.raise_signal(signal.SIGALRM) | ||
| 56 | + assert rearmed == [signal.SIGALRM], rearmed | ||
| 57 | + assert signal.getsignal(signal.SIGALRM) is signal.SIG_IGN | ||
| 58 | + | ||
| 59 | + # The same goes for arming a different signal from inside a handler. | ||
| 60 | + armed = [] | ||
| 61 | + | ||
| 62 | + def target(signum, frame): | ||
| 63 | + armed.append("target") | ||
| 64 | + | ||
| 65 | + def arm_other(signum, frame): | ||
| 66 | + armed.append("arm_other") | ||
| 67 | + signal.signal(signal.SIGUSR2, target) | ||
| 68 | + | ||
| 69 | + signal.signal(signal.SIGUSR1, arm_other) | ||
| 70 | + signal.raise_signal(signal.SIGUSR1) | ||
| 71 | + assert armed == ["arm_other"], armed | ||
| 72 | + assert signal.getsignal(signal.SIGUSR2) is target | ||
| 73 | + | ||
| 74 | + signal.raise_signal(signal.SIGUSR2) | ||
| 75 | + assert armed == ["arm_other", "target"], armed | ||
| 76 | + | ||
| 77 | + signal.signal(signal.SIGALRM, signal.SIG_DFL) | ||
| 78 | + signal.signal(signal.SIGUSR1, signal.SIG_DFL) | ||
| 79 | + signal.signal(signal.SIGUSR2, signal.SIG_DFL) | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments