opencode icon indicating copy to clipboard operation
opencode copied to clipboard

Add timeout for file watcher subscribe to address hangs on Rosetta x86 emulation

Open matthewijordan opened this issue 1 month ago • 3 comments

Summary

  • Fixes file watcher hanging indefinitely on x86 emulation via Rosetta on macOS (parcel-bundler/watcher#159)
  • If timeout occurs, automatic detection of git branch switches and external file changes will not work. An error is logged when this happens.

Minimal Reproduction Steps

Environment

  • macOS with Apple Silicon (M1/M2/M3)
  • Docker Desktop with Rosetta emulation enabled
  • x86_64 Linux container running under Rosetta

Dockerfile

FROM --platform=linux/amd64 ubuntu:22.04

RUN apt-get update && apt-get install -y curl ca-certificates git && rm -rf /var/lib/apt/lists/*
RUN useradd -m -s /bin/bash testuser
RUN curl -fsSL https://opencode.ai/install | bash
RUN mv /root/.opencode/bin/opencode /usr/local/bin/opencode
RUN mkdir -p /work/repo && cd /work/repo && git init && echo '{"name":"test"}' > package.json && chown -R testuser:testuser /work/repo

WORKDIR /work/repo
USER testuser
CMD ["bash"]

Steps to Reproduce

# Build and start container
docker build --platform=linux/amd64 -t opencode-repro .
docker run --platform=linux/amd64 -d --name opencode-test opencode-repro sleep infinity

# Start opencode (first time - works)
docker exec -d opencode-test bash -c "opencode serve --port=4096 > /tmp/opencode.log 2>&1"
sleep 5

# Create a session
docker exec opencode-test curl -s -X POST http://localhost:4096/session -H 'Content-Type: application/json' -d '{}'

# Restart container
docker restart opencode-test
sleep 2

# Start opencode again (second time - HANGS)
docker exec -d opencode-test bash -c "opencode serve --port=4096 > /tmp/opencode.log 2>&1"
sleep 10

# This will timeout
docker exec opencode-test curl -s --max-time 10 http://localhost:4096/session
# Returns nothing - server is hung

Root Cause

@parcel/watcher's subscribe() function hangs under Rosetta x86_64 emulation. When inotify_init1() fails or behaves unexpectedly under Rosetta, the watcher's Backend::run blocks forever instead of propagating the error (see parcel-bundler/watcher#159).

This blocks the event loop, causing all subsequent async operations to hang - including file reads needed to load session data.

Verified

Environment Result
Native ARM64 Ubuntu container ✅ Works
x64 Ubuntu container under Rosetta ❌ Hangs
x64 container with timeout fix ✅ Works

matthewijordan avatar Dec 10 '25 23:12 matthewijordan

/review

rekram1-node avatar Dec 11 '25 00:12 rekram1-node

/review

rekram1-node avatar Dec 11 '25 01:12 rekram1-node

lgtm

github-actions[bot] avatar Dec 11 '25 01:12 github-actions[bot]