aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-php-rpc/src/session.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-16 14:18:41 +0900
committernsfisis <nsfisis@gmail.com>2026-08-16 14:35:48 +0900
commitaa2124fe5d0c96078c034a6e4044b7e81acdf692 (patch)
treec9b1597fef555220676f6a5ae554dc81579a4269 /crates/shirabe-php-rpc/src/session.rs
parentb4ab3df2ec85fbe477d7721344a8cd3630b437a1 (diff)
downloadphp-shirabe-aa2124fe5d0c96078c034a6e4044b7e81acdf692.tar.gz
php-shirabe-aa2124fe5d0c96078c034a6e4044b7e81acdf692.tar.zst
php-shirabe-aa2124fe5d0c96078c034a6e4044b7e81acdf692.zip
feat(php-rpc): replay Rust-side env writes into the PHP worker
The worker is a long-lived child holding the environment it was handed at spawn, so `@putenv`, the bin dir the event dispatcher prepends to PATH, and COMPOSER_DEV_MODE never reached the PHP code running in it. The shim now journals every write to the three storages PHP exposes, and the outermost rpc_call replays the entries the worker has not seen yet through __shirabe_sync_env. Replaying the writes rather than pushing a whole snapshot keeps the worker's own $_SERVER entries intact. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe-php-rpc/src/session.rs')
-rw-r--r--crates/shirabe-php-rpc/src/session.rs27
1 files changed, 19 insertions, 8 deletions
diff --git a/crates/shirabe-php-rpc/src/session.rs b/crates/shirabe-php-rpc/src/session.rs
index 29bd89f3..3e1a817d 100644
--- a/crates/shirabe-php-rpc/src/session.rs
+++ b/crates/shirabe-php-rpc/src/session.rs
@@ -16,18 +16,19 @@ struct SessionLock {
}
impl SessionLock {
- fn acquire(&self) {
+ /// Returns whether this acquisition opened the session rather than re-entering one.
+ fn acquire(&self) -> bool {
let mut owner = self.owner.lock().unwrap();
let me = std::thread::current().id();
loop {
match *owner {
None => {
*owner = Some((me, 1));
- return;
+ return true;
}
Some((tid, depth)) if tid == me => {
*owner = Some((me, depth + 1));
- return;
+ return false;
}
Some(_) => {
owner = self.cvar.wait(owner).unwrap();
@@ -60,12 +61,20 @@ static SESSION: LazyLock<SessionLock> = LazyLock::new(|| SessionLock {
/// RAII guard; acquired once at the outermost `rpc_call`, re-entered (depth += 1, no blocking)
/// by nested calls from the same thread.
-pub struct SessionGuard;
+pub struct SessionGuard {
+ outermost: bool,
+}
impl SessionGuard {
pub fn enter() -> Self {
- SESSION.acquire();
- SessionGuard
+ let outermost = SESSION.acquire();
+ SessionGuard { outermost }
+ }
+
+ /// Whether this guard opened the session. Work that must happen once per logical call
+ /// session, before anything else crosses the boundary, keys off this.
+ pub fn is_outermost(&self) -> bool {
+ self.outermost
}
}
@@ -81,8 +90,10 @@ mod tests {
#[test]
fn same_thread_reenters_without_blocking() {
- let _outer = SessionGuard::enter();
- let _inner = SessionGuard::enter();
+ let outer = SessionGuard::enter();
+ let inner = SessionGuard::enter();
+ assert!(outer.is_outermost());
+ assert!(!inner.is_outermost());
}
#[test]