Skip to content

Mouse Input Spam / SIGPWR Signal Storm in WSL2 #5168

Closed as not planned
Closed as not planned

Description

@wilfchun

Mouse Input Spam / SIGPWR Signal Storm in WSL2

Description

When running opencode in NixOS on WSL2, the application becomes unusable due to continuous SIGPWR (power signal) spam. The application sends itself hundreds of SIGPWR signals per second, causing write operations to continuously restart and creating what appears as "mouse input spamming."

Environment

  • OS: Linux nixos 6.6.87.2-microsoft-standard-WSL2
  • WSL Version: 2.6.2.0
  • Kernel: 6.6.87.2-1
  • Terminal: xterm-256color
  • OpenCode Version: 1.0.20
  • Platform: NixOS on WSL2

Steps to Reproduce

  1. Install opencode 1.0.20 on NixOS running in WSL2
  2. Run opencode in any directory
  3. Observe the TUI becoming unresponsive with continuous signal spam

Expected Behavior

The opencode TUI should run normally with mouse tracking enabled, responding to user input without signal spam.

Actual Behavior

The application sends itself continuous SIGPWR signals, causing:

  • Write operations to restart repeatedly (ERESTARTSYS)
  • Mouse input appearing to spam
  • The TUI becoming effectively unusable
  • High CPU usage due to signal handling

Evidence from strace

Running strace -e signal,write opencode shows:

write(1, "\33[?2027h\33[?2004h\33[?1000h\33[?1002h\33[?1003h", 48) = 48
write(1, "\33[14t", 5) = 5
--- SIGPWR {si_signo=SIGPWR, si_code=SI_TKILL, si_pid=380205, si_uid=1000} ---
--- SIGPWR {si_signo=SIGPWR, si_code=SI_TKILL, si_pid=380205, si_uid=1000} ---
--- SIGPWR {si_signo=SIGPWR, si_code=SI_TKILL, si_pid=380205, si_uid=1000} ---
[... hundreds more SIGPWR signals ...]
write(1, "5m\33[48;2;34;36;54m              "..., 7274) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
--- SIGPWR {si_signo=SIGPWR, si_code=SI_TKILL, si_pid=380205, si_uid=1000} ---

The key observations:

  1. Line 60 in strace shows mouse tracking being enabled: \33[?1000h\33[?1002h\33[?1003h
  2. Immediately after, SIGPWR signals start flooding
  3. The process sends signals to itself (same PID: 380205)
  4. Write operations repeatedly get ERESTARTSYS due to signal interruption

Analysis

The SIGPWR signals are being generated internally by the opencode process (SI_TKILL with same PID), suggesting this is either:

  1. A bug in the Bun runtime's signal handling on WSL2
  2. An issue with opencode's async/threading implementation
  3. A WSL2-specific interaction with the TUI library used

Workarounds Attempted

None of these resolved the issue:

  • Setting trap "" PWR to block SIGPWR
  • Changing TERM to different values
  • Disabling mouse tracking escape sequences
  • Running with setsid
  • Using different terminal emulators

Related Issues

However, none of these mention the SIGPWR signal spam specifically.

Additional Context

This appears to be WSL2-specific, as the issue does not occur on native Linux systems. The signal storm begins immediately after the TUI initializes mouse tracking, suggesting a correlation between mouse tracking and the signal handling bug.

Activity

  1. added
    opentuiThis relates to changes in v1.0, now that opencode uses opentui
    on Dec 6, 2025
  2. github-actions commented on Dec 6, 2025

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    The common thread appears to be WSL-specific TUI/input handling issues that emerged after the opentui migration. Feel free to ignore if your SIGPWR signal spam issue is distinct from these.

  3. gagapony commented on Jan 12, 2026

    @gagapony

    I just used the official OpenCode flake.nix to build the app, and it works fine.
    gagapony/nixosdots@cfcbb64

  4. thdxr commented on Mar 25, 2026

    @thdxr
    Member

    To stay organized issues are automatically closed after 90 days of no activity. If the issue is still relevant please open a new one.

  5. removed
    opentuiThis relates to changes in v1.0, now that opencode uses opentui
    on May 3, 2026
  6. alexeygrigorev commented on Oct 6, 2026

    @alexeygrigorev

    Affected by it too

  7. alexeygrigorev commented on Oct 6, 2026

    @alexeygrigorev

    Adding an independent data point: the underlying mouse-tracking leak reproduces outside WSL2, on a completely different platform, and is still present in current opencode — with byte-level evidence of exactly what gets left behind, plus workarounds that operate on the right layer.

    Environment

    • opencode 1.18.34 (npm global; the TUI is opentui-based — the session opens with the \e]99;i=opentui-notifications announce)
    • Host: Windows 11 (10.0.26200), OpenSSH for Windows, DefaultShell = Git Bash (MINGW64, bash 5.3.15)
    • Client: Windows Terminal, plain ssh -tt <host> opencode

    What the byte stream shows (captured with a small pty harness around ssh -tt, timestamps aligned)

    Startup:

    \e[?1000h \e[?1002h \e[?1003h \e[?1006h
    

    Exit via Ctrl+C — the entire teardown:

    \e]22;\a \e[>4;0m \e[?2004l \e[?1049l \e[?2031l \e]0;\a \e[0 q \e[?25l \e[H \e[K ...
    

    It restores bracketed paste (2004), the alternate screen (1049), mode 2031, cursor style and visibility — but the full capture contains zero occurrences of \e[?1000l, \e[?1002l, \e[?1003l or \e[?1006l. The terminal is left in all-motion mouse reporting (1003 + SGR 1006) after the TUI is gone.

    Fallout — back at the shell prompt, every pointer movement over the window makes the terminal send \e[<35;<col>;<row>M (motion, no button) into the shell, which prints it literally:

    $ 35;48;15M35;46;16M35;45;17M35;44;18M35;44;19M…
    

    I reproduced that exact garbage by writing a single SGR report (\e[<35;48;15M) to the bash prompt on the host — it echoes 35;48;15M. I suspect this is also the shape behind the "mouse input spam" here and in #5046: with the TUI gone, the reports keep coming — from the terminal, not from opencode. (Whether WSL2 additionally turns the leftover reporting into a SIGPWR storm is a separate question, but the leaked mouse state is real on its own, platform-independent, and trivial to trigger.)

    Reproduce

    1. ssh -tt <host> opencode — any host, any terminal
    2. Exit with Ctrl+C
    3. Move the mouse over the terminal → motion reports accumulate at the prompt

    Workarounds that work — the ones tried in the OP (trap "" PWR, setsid, TERM changes) act on the wrong layer: the leftover state lives in the terminal, so the fix is to emit the mouse-off reset, not to trap signals.

    One-off, at the affected prompt:

    printf '\033[?1000l\033[?1002l\033[?1003l\033[?1005l\033[?1006l\033[?1015l\033[?1016l'

    Permanent, in the host's ~/.bashrc (resets at every prompt; TUIs re-enable the modes when they start; the guard keeps it from stacking):

    __tty_reset_mouse() {
      printf '\033[?1000l\033[?1002l\033[?1003l\033[?1005l\033[?1006l\033[?1015l\033[?1016l'
    }
    case ";${PROMPT_COMMAND:-};" in
      *";__tty_reset_mouse;"*) ;;
      *) PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND; }__tty_reset_mouse" ;;
    esac

    Or wrap the launch command and restore right after exit:

    oc() {
      opencode --auto "$@"
      local rc=$?
      [[ -t 1 ]] && printf '\033[?1000l\033[?1002l\033[?1003l\033[?1005l\033[?1006l\033[?1015l\033[?1016l'
      return $rc
    }

    The real fix is presumably a small addition to the opentui teardown: emit the mouse-mode disables next to the existing ?2004l / ?1049l restores. Happy to share the raw captures if useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions