You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 0335742
Browse filesBrowse the repository at this point in the historyBrowse files
Dev agent: release builds open no port; 32-byte token minimum; port cannot be taken over (#233)
- The runtime starts the agent only when the variable is set and an installed
payload root holds python_multiplatform_devagent.enable. The library is one
artifact for debug and release, so the app's build decides: toolchain stages
the marker into debug variants only. Without it the variable is ignored with
a warning.
- The token must be at least 43 characters (secrets.token_urlsafe(32)), or the
agent refuses to start.
- Windows sets SO_EXCLUSIVEADDRUSE. POSIX keeps SO_REUSEADDR only to rebind the
launcher's port past TIME_WAIT; it does not let another socket bind the port
while the agent listens (tested).
- stop() deadlocked on the reader lock while a connection was blocked in a
read; it now shuts the socket down and the serving thread closes itself.
Copy file name to clipboardExpand all lines: docs/SPEC.md
+19-11Lines changed: 19 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -136,18 +136,26 @@ fail, then implement.
136
136
(resolution order; the simulator test task's `PYTHONHOME` still wins). The installed-app run on the
137
137
simulator is a manual check, `docs/platforms/ios-app-bundle.md`.
138
138
-**L-12** The dev agent (#233; toolchain `docs/design/live-connection.md`, option B): when the launcher sets
139
-
`PYTHON_MULTIPLATFORM_DEV_AGENT` to `port=<n>;token=<t>[;overlay=<dir>]` (a debug launch; a release build
140
-
never does), `Python3.initialize()` loads the embedded agent (`src/commonMain/python/
141
-
python_multiplatform_devagent.py`, generated into Kotlin by `generateDevAgentSource`) as the module
142
-
`python_multiplatform_devagent` and it listens on 127.0.0.1 only. A connection's first message must be
143
-
`hello` with the token. Then, one JSON object per line: `execute` runs code in `__main__`'s persistent
144
-
namespace, streams stdout and stderr, returns the last expression's value and reports errors with their
145
-
traceback; `complete` completes from that namespace; `push` writes `.py` files into a writable overlay first
146
-
on `sys.path` and re-imports the loaded ones, children first, through `typedpython.importgate` when the app
147
-
has it (N-7b), keeping the old module when a re-import is refused or fails. A malformed request is printed
139
+
`PYTHON_MULTIPLATFORM_DEV_AGENT` to `port=<n>;token=<t>[;overlay=<dir>]`**and** an installed payload root
140
+
holds the marker `python_multiplatform_devagent.enable`, `Python3.initialize()` loads the embedded agent
141
+
(`src/commonMain/python/python_multiplatform_devagent.py`, generated into Kotlin by `generateDevAgentSource`)
142
+
as the module `python_multiplatform_devagent` and it listens on 127.0.0.1 only. The marker is the build-time
143
+
switch: this library is one artifact for debug and release, so the app's build decides, and toolchain stages
144
+
the marker into debug variants only. Without it the variable is ignored with a warning and no port opens. The
145
+
token must be at least 43 characters (`secrets.token_urlsafe(32)`), or the agent refuses to start. The listening
146
+
socket cannot be bound by another socket while it listens: `SO_EXCLUSIVEADDRUSE` on Windows; on POSIX,
147
+
`SO_REUSEADDR` only so that a restarted app can rebind the launcher's port past TIME_WAIT. A connection's first
148
+
message must be `hello` with the token. Then, one JSON object per line: `execute` runs code in `__main__`'s
149
+
persistent namespace, streams stdout and stderr, returns the last expression's value and reports errors with
150
+
their traceback; `complete` completes from that namespace; `push` writes `.py` files into a writable overlay
151
+
first on `sys.path` and re-imports the loaded ones, children first, through `typedpython.importgate` when the
152
+
app has it (N-7b), keeping the old module when a re-import is refused or fails. A malformed request is printed
148
153
and does not stop the app. `Status: partial`: desktop
149
-
(`PM/desktopTest/.../env/PythonDevAgentTest.kt`: the embedded agent answers over loopback, and a child JVM started with the variable has an agent on that port while one started without it has none; the protocol, `python-multiplatform/src/test/python/
150
-
test_devagent.py`, CI `Dev agent protocol tests`); nothing sets the variable on Android or iOS yet
154
+
(`PM/desktopTest/.../env/PythonDevAgentTest.kt`: the embedded agent answers over loopback; a child JVM with the
155
+
marker and the variable has an agent on that port, one without the variable has none, one without the marker
156
+
(a release build) opens no port with the variable set, and a short token opens no port; the protocol, token
157
+
length, port takeover and restart: `python-multiplatform/src/test/python/test_devagent.py`, CI `Dev agent
158
+
protocol tests`, macOS only so far); nothing sets the variable or stages the marker on Android or iOS yet
151
159
(toolchain's M2, M3); no interrupt; `execute` runs on the agent's thread (no main-thread dispatch yet).
0 commit comments