Skip to content

Commit 0be647f

Browse files
authored
perf: reduce container startup idle wait by ~5s (#1851)
* Initial plan * perf: reduce container startup idle wait times - Replace unconditional `sleep 5` with poll-based wait (up to 1s, 100ms intervals) in both chroot and non-chroot paths of entrypoint.sh. Fast commands exit early without paying the full wait. Saves ~4s on every invocation. - Reduce DoH proxy healthcheck start_period from 10s to 2s and interval from 5s to 1s, matching the Squid proxy timings. - Reduce Squid log flush delay from 500ms to 200ms. - Update documentation to reflect the new timing. Agent-Logs-Url: https://github.com/github/gh-aw-firewall/sessions/564848fc-f657-47bf-94b2-86ed2b542f0b --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 4fba994 commit 0be647f

4 files changed

Lines changed: 30 additions & 16 deletions

File tree

containers/agent/entrypoint.sh

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -810,8 +810,13 @@ AWFEOF
810810
" &
811811
AGENT_PID=$!
812812

813-
# Wait for agent to initialize and cache tokens (5 seconds)
814-
sleep 5
813+
# Wait for agent to initialize and cache tokens (up to 1 second)
814+
# The one-shot-token LD_PRELOAD library caches tokens in ~100ms during process init.
815+
# Poll every 100ms so fast commands (e.g. 'echo ok') don't pay the full wait.
816+
for _i in 1 2 3 4 5 6 7 8 9 10; do
817+
kill -0 "$AGENT_PID" 2>/dev/null || break
818+
sleep 0.1
819+
done
815820

816821
# Unset all sensitive tokens from parent shell environment
817822
unset_sensitive_tokens
@@ -872,8 +877,13 @@ else
872877
fi
873878
AGENT_PID=$!
874879

875-
# Wait for agent to initialize and cache tokens (5 seconds)
876-
sleep 5
880+
# Wait for agent to initialize and cache tokens (up to 1 second)
881+
# The one-shot-token LD_PRELOAD library caches tokens in ~100ms during process init.
882+
# Poll every 100ms so fast commands (e.g. 'echo ok') don't pay the full wait.
883+
for _i in 1 2 3 4 5 6 7 8 9 10; do
884+
kill -0 "$AGENT_PID" 2>/dev/null || break
885+
sleep 0.1
886+
done
877887

878888
# Unset all sensitive tokens from parent shell environment
879889
unset_sensitive_tokens

docs/authentication-architecture.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ char* getenv(const char* name) {
313313

314314
**Source:** `containers/agent/entrypoint.sh`
315315

316-
The entrypoint (PID 1) runs the agent command in the background, then unsets sensitive tokens from its own environment after a 5-second grace period:
316+
The entrypoint (PID 1) runs the agent command in the background, then unsets sensitive tokens from its own environment after a brief grace period (up to 1 second, polling every 100ms):
317317

318318
```bash
319319
unset_sensitive_tokens() {
@@ -336,7 +336,11 @@ unset_sensitive_tokens() {
336336
# Run agent in background, wait for it to cache tokens, then unset
337337
capsh --drop=cap_net_admin -- -c "exec gosu awfuser $COMMAND" &
338338
AGENT_PID=$!
339-
sleep 5
339+
# Poll every 100ms for up to 1s; exit early if agent finishes
340+
for _i in 1 2 3 4 5 6 7 8 9 10; do
341+
kill -0 "$AGENT_PID" 2>/dev/null || break
342+
sleep 0.1
343+
done
340344
unset_sensitive_tokens
341345
wait $AGENT_PID
342346
```

docs/token-unsetting-fix.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ Modified the entrypoint to unset all sensitive tokens from its own environment a
1717

1818
2. **Modified chroot mode execution** (entrypoint.sh:449-468)
1919
- Changed from `exec chroot ...` to `chroot ... &` (run in background)
20-
- Added 5-second sleep to allow agent to initialize and cache tokens
20+
- Added poll-based wait (up to 1 second, 100ms intervals) to allow agent to initialize and cache tokens
2121
- Call `unset_sensitive_tokens()` to clear tokens from parent shell
2222
- Use `wait $AGENT_PID` to wait for agent completion
2323
- Exit with agent's exit code
2424

2525
3. **Modified non-chroot mode execution** (entrypoint.sh:484-499)
2626
- Changed from `exec capsh ...` to `capsh ... &` (run in background)
27-
- Added 5-second sleep to allow agent to initialize and cache tokens
27+
- Added poll-based wait (up to 1 second, 100ms intervals) to allow agent to initialize and cache tokens
2828
- Call `unset_sensitive_tokens()` to clear tokens from parent shell
2929
- Use `wait $AGENT_PID` to wait for agent completion
3030
- Exit with agent's exit code
@@ -47,15 +47,15 @@ The following tokens are unset from the entrypoint's environment:
4747

4848
1. **t=0s**: Container starts, entrypoint receives tokens in environment
4949
2. **t=0s**: Entrypoint starts agent command in background
50-
3. **t=0-5s**: Agent initializes, reads tokens via getenv(), one-shot-token library caches them
51-
4. **t=5s**: Entrypoint calls `unset_sensitive_tokens()`, clearing tokens from `/proc/1/environ`
52-
5. **t=5s+**: Agent continues running with cached tokens, `/proc/1/environ` no longer contains tokens
50+
3. **t=0-1s**: Agent initializes, reads tokens via getenv(), one-shot-token library caches them
51+
4. **t=≤1s**: Entrypoint calls `unset_sensitive_tokens()`, clearing tokens from `/proc/1/environ`
52+
5. **t=≤1s+**: Agent continues running with cached tokens, `/proc/1/environ` no longer contains tokens
5353
6. **t=end**: Agent completes, entrypoint exits with agent's exit code
5454

5555
### Security Impact
5656

5757
- **Before**: Tokens accessible via `/proc/1/environ` throughout agent execution
58-
- **After**: Tokens accessible via `/proc/1/environ` only for first 5 seconds, then cleared
58+
- **After**: Tokens accessible via `/proc/1/environ` only for up to 1 second, then cleared
5959
- **Agent behavior**: Unchanged - agent can still read tokens via getenv() (cached by one-shot-token library)
6060

6161
### Testing
@@ -75,6 +75,6 @@ Manual test script at `test-token-unset.sh`:
7575

7676
## Notes
7777

78-
- The 5-second delay is necessary to give the agent process time to initialize and cache tokens via the one-shot-token library before the parent shell unsets them
78+
- The poll-based wait (up to 1 second, checking every 100ms) gives the agent process time to initialize and cache tokens via the one-shot-token library before the parent shell unsets them. Fast commands exit early without waiting the full second.
7979
- Both token lists (entrypoint.sh and one-shot-token library) must be kept in sync when adding new token types
8080
- The exit code handling is preserved - the entrypoint exits with the agent's exit code

src/docker-manager.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,10 +1658,10 @@ export function generateDockerCompose(
16581658
command: ['proxy-dns', '--address', '0.0.0.0', '--port', '53', '--upstream', config.dnsOverHttps],
16591659
healthcheck: {
16601660
test: ['CMD', 'nslookup', '-port=53', 'cloudflare.com', '127.0.0.1'],
1661-
interval: '5s',
1661+
interval: '1s',
16621662
timeout: '3s',
16631663
retries: 5,
1664-
start_period: '10s',
1664+
start_period: '2s',
16651665
},
16661666
// Security hardening: Drop all capabilities
16671667
cap_drop: ['ALL'],
@@ -2301,7 +2301,7 @@ export async function runAgentCommand(workDir: string, allowedDomains: string[],
23012301
logger.debug(`Agent exit code: ${exitCode}`);
23022302

23032303
// Small delay to ensure Squid logs are flushed to disk
2304-
await new Promise(resolve => setTimeout(resolve, 500));
2304+
await new Promise(resolve => setTimeout(resolve, 200));
23052305

23062306
// Check Squid logs to see if any domains were blocked (do this BEFORE cleanup)
23072307
const { hasDenials, blockedTargets } = await checkSquidLogs(workDir, proxyLogsDir);

0 commit comments

Comments
 (0)