Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions pyre/extra_tests/snippets/stdlib_re.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,22 @@

# Combining characters; issue #7518
assert not re.match(r"\w", "\u0345"), r"\w should not match U+0345 (category Mn)"


# A group selector is taken as a number when its type has `__index__`, and as a
# name otherwise, so a duck-typed operand reaches every span accessor.
class DuckIndex:
def __index__(self):
return 1


mo = re.compile("(a+)(b+)").match("aabb")
assert mo.group(DuckIndex()) == "aa"
assert mo[DuckIndex()] == "aa"
assert mo.start(DuckIndex()) == 0
assert mo.end(DuckIndex()) == 2
assert mo.span(DuckIndex()) == (0, 2)
assert mo.group(DuckIndex(), DuckIndex()) == ("aa", "aa")

mo = re.compile("(?P<first>a+)(?P<second>b+)").match("aabb")
assert mo.group("second") == "bb"
8 changes: 6 additions & 2 deletions pyre/pyre-interpreter/src/module/signal/interp_signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,12 @@ pub fn install_signal_handling(ec: &mut ExecutionContext) {
Box::leak(CheckSignalAction::new(ec.space));
action.register_periodic_action(ec.actionflag.shared_mut(), false);

// Hand the ticker cell address to the OS handler so it can force the
// ticker negative (rsignal.py:31-32 `pypysig_getaddr_occurred`).
// Hand the ticker cell address to the OS handler (rsignal.py:31-32
// `pypysig_getaddr_occurred`). The handler itself only arms the
// eval-breaker's async bit, which is a lock-free atomic RMW and so
// async-signal-safe; `ExecutionContext::bytecode_trace` is what turns
// that request into a negative ticker, under the GIL. Writing this
// cell from the handler would not be signal-safe.
let ticker_addr = ec.actionflag.ticker_addr();
signalstate::register_ticker(ticker_addr);

Expand Down
16 changes: 10 additions & 6 deletions pyre/pyre-interpreter/src/module/signal/signalstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ pub fn get_wakeup_fd_write_errno() -> i32 {
WAKEUP_FD_WRITE_ERRNO.swap(0, Ordering::SeqCst)
}

/// Register the address of the `ActionFlag` ticker so the OS handler can
/// force it negative. Called once at startup from
/// `install_signal_handling`.
/// Register the address of the `ActionFlag` ticker. The OS handler never
/// writes this cell — it arms the eval-breaker's async bit and lets
/// `sync_async_ticker` make the ticker negative under the GIL — so the address
/// serves to identify which ticker the shared breaker drives. Called once at
/// startup from `install_signal_handling`.
pub fn register_ticker(ptr: *mut isize) {
TICKER_PTR.store(ptr, Ordering::SeqCst);
}
Expand All @@ -69,9 +71,11 @@ pub(crate) fn rearm_ticker() {

// ── pending-signal bitmask (signals.c pypysig_pushback / pypysig_poll) ──

/// `signals.c:98-114 pypysig_pushback` — set the pending bit for
/// `signum` and force the ticker to -1. Both the OS handler and
/// `set_interrupt` reach signal delivery through here.
/// `signals.c:98-114 pypysig_pushback` — set the pending bit for `signum` and
/// arm the eval-breaker's async bit. Upstream's handler drives the ticker
/// negative here; this defers that write to `sync_async_ticker` under the GIL
/// so the whole path stays two lock-free atomics, which is what lets the OS
/// handler call it. `set_interrupt` reaches signal delivery through here too.
pub fn signal_pushback(signum: i32) {
if (0..NSIG).contains(&signum) {
let bitmask = 1i64 << signum;
Expand Down
Loading