blob: af4c947afd617a10ae07ea6030ca480f6487f3c8 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
# Environment variable porting
PHP exposes three distinct ways to read process environment variables: the `$_ENV` and `$_SERVER`
superglobals, and `getenv()`/`putenv()`. They look interchangeable but are not, so Shirabe ports
each to a separate construct in `crates/shirabe-php-shim/src/env.rs`. Choose the porting target by
matching the exact PHP construct used in Composer; do not substitute one for another.
## The three are not interchangeable
The three differ in what they observe and when:
* `getenv()`/`putenv()` read and write the real environment variables. `putenv()` mutates the
live process environment, so a value set with `putenv()` is inherited by child processes spawned
afterwards.
* `$_ENV` and `$_SERVER` are snapshots taken at startup. They are populated once when the
process starts and are not kept in sync afterwards. A later `putenv()` does *not* appear in
`$_ENV`/`$_SERVER`, and assigning to `$_ENV`/`$_SERVER` does *not* change the real environment.
* `$_ENV` and `$_SERVER` are not shared with child processes. Launching an external program via `system()`
and friends passes along the real environment (as mutated by `putenv()`), not the
`$_ENV`/`$_SERVER` snapshot.
* Also, `$_ENV` and `$_SERVER` have their own storage; they are not shared.
Because of these differences, porting must preserve which of the three Composer actually used at
each call site.
## Mapping
| PHP | Shirabe |
| --- | --- |
| `getenv()` | `getenv()`/`getenv_all()` |
| `putenv("K=V")` | `putenv()` |
| `putenv("K")` (unset) | `putenv_clear()` |
| `$_ENV` | `PHP_ENV` |
| `$_SERVER` | `PHP_SERVER` |
## Reaching the PHP runtime
The PHP worker is a separate, long-lived process (`docs/dev/php-rpc.md`): it holds the environment
it was handed at spawn, so a later write on the Rust side would be invisible to the PHP code
running in it. Every write to one of the three storages is therefore recorded in an ordered journal
(`env_mutations_since`), and `shirabe-php-rpc` replays the entries the worker has not seen yet —
through `__shirabe_sync_env`, which writes each entry to the storage it names — before the next call
crosses the boundary. Replaying the writes rather than pushing a whole snapshot is what keeps the
worker's own `$_SERVER` entries (`argv`, `SCRIPT_NAME`, ...) intact.
## TODOs
Reflecting PHP-side mutations of `$_ENV`/`$_SERVER` back into Shirabe is unimplemented. How to
handle the case where PHP code rewrites `$_ENV` or `$_SERVER` is still TBD.
|