Replay exec-server shell snapshots through unnamed files (#48078)

## Why

Large shell snapshots need a replay path that does not add their state to the child process environment.

## What changed

- Keep captured state cached in memory and give each Bash or Zsh launch an independent, read-only file descriptor to source. Unlink the file before writing shell state, create it under the sandbox-protected daemon directory, and close the carrier descriptor before restoring functions.
- Probe descriptor-path access inside the capture sandbox. Retain environment replay for `sh` and when descriptor paths are unavailable; use normal shell startup if preparing the replay file fails.
- Group options and aliases during capture so sourcing preserves their parsing behavior.

## Testing

Add coverage for concurrent replays with 480 KiB payloads, pipe and TTY execution, stdin preservation, descriptor cleanup, sandbox protection, blocked descriptor-path fallback, and alias/option parsing equivalence.

GitOrigin-RevId: 8103d5c37ce4d1885628a4efba3551549f12bea8
This commit is contained in:
jif
2026-09-25 12:23:15 +00:00
committed by copyberry
parent 466d5f583e
commit c98e263fb5
13 changed files with 541 additions and 38 deletions
@@ -42,6 +42,36 @@ pub struct SnapshotCaptureOptions {
pub fn snapshot_capture_script(
shell_type: ShellType,
options: SnapshotCaptureOptions,
) -> Option<String> {
capture_script(shell_type, options, Replay::Eval)
}
/// Capture state for incremental sourcing. Parse options and aliases together so
/// restored aliases and quoting options cannot reinterpret later declarations.
pub fn snapshot_source_capture_script(
shell_type: ShellType,
options: SnapshotCaptureOptions,
) -> Option<String> {
capture_script(
shell_type,
options,
if shell_type == ShellType::Sh {
Replay::Eval
} else {
Replay::Source
},
)
}
enum Replay {
Eval,
Source,
}
fn capture_script(
shell_type: ShellType,
options: SnapshotCaptureOptions,
replay: Replay,
) -> Option<String> {
let script = match shell_type {
ShellType::Zsh => zsh_snapshot_script(options.startup),
@@ -56,6 +86,8 @@ pub fn snapshot_capture_script(
};
Some(
script
.replace("SNAPSHOT_OPTIONS_BEGIN", match replay { Replay::Eval => "", Replay::Source => "printf '{\\n'" })
.replace("SNAPSHOT_ALIASES_END", match replay { Replay::Eval => "", Replay::Source => "printf \"case '' in '') ;; esac\\n}\\n\"" })
.replace("SNAPSHOT_EXPORTS", &declarations)
.replace(
"SNAPSHOT_DECLARATION_ENVIRONMENT",
@@ -92,16 +124,18 @@ print 'unalias -a 2>/dev/null || true'
print '# Functions'
functions
print ''
SNAPSHOT_OPTIONS_BEGIN
SNAPSHOT_COMMAND_HELPER
setopt_count=$(setopt | __codex_snapshot_command wc -l | __codex_snapshot_command tr -d ' ')
print "# setopts $setopt_count"
setopt | __codex_snapshot_command sed 's/^/setopt /'
print ''
printf '\0'
alias_count=$(alias -L | __codex_snapshot_command wc -l | __codex_snapshot_command tr -d ' ')
alias_count=$(\alias -L | __codex_snapshot_command wc -l | __codex_snapshot_command tr -d ' ')
print "# aliases $alias_count"
alias -L
\alias -L
print ''
SNAPSHOT_ALIASES_END
printf '\0'
SNAPSHOT_EXPORTS
printf '\0'
@@ -122,6 +156,7 @@ shopt -p || true
echo '# Functions'
declare -f
echo ''
SNAPSHOT_OPTIONS_BEGIN
SNAPSHOT_COMMAND_HELPER
bash_opts=$(set -o | __codex_snapshot_command awk '$2=="on"{print $1}')
bash_opt_count=$(printf '%s\n' "$bash_opts" | __codex_snapshot_command sed '/^$/d' | __codex_snapshot_command wc -l | __codex_snapshot_command tr -d ' ')
@@ -131,10 +166,11 @@ if [ -n "$bash_opts" ]; then
fi
echo ''
printf '\0'
alias_count=$(alias -p | __codex_snapshot_command wc -l | __codex_snapshot_command tr -d ' ')
alias_count=$(\alias -p | __codex_snapshot_command wc -l | __codex_snapshot_command tr -d ' ')
echo "# aliases $alias_count"
alias -p
\alias -p
echo ''
SNAPSHOT_ALIASES_END
printf '\0'
SNAPSHOT_EXPORTS
printf '\0'
@@ -180,6 +216,7 @@ elif command -v declare >/dev/null 2>&1; then
declare -f
fi
echo ''
SNAPSHOT_OPTIONS_BEGIN
SNAPSHOT_COMMAND_HELPER
if set -o >/dev/null 2>&1; then
sh_opts=$(set -o | __codex_snapshot_command awk '$2=="on"{print $1}')
@@ -201,6 +238,7 @@ if alias >/dev/null 2>&1; then
else
echo '# aliases 0'
fi
SNAPSHOT_ALIASES_END
printf '\0'
SNAPSHOT_EXPORTS
printf '\0'