Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server doesn't exit when STDIN is closed #19091

Open
7 tasks done
stevehodgkiss opened this issue Dec 28, 2024 · 0 comments · May be fixed by #19092
Open
7 tasks done

Server doesn't exit when STDIN is closed #19091

stevehodgkiss opened this issue Dec 28, 2024 · 0 comments · May be fixed by #19092

Comments

@stevehodgkiss
Copy link

stevehodgkiss commented Dec 28, 2024

Describe the bug

When running Vite as a dev watcher inside a Phoenix project, the Vite server remains running in the background after exiting the Phoenix server with ctrl+c.

# config/dev.exs
config :myapp, MyApp.Endpoint,
  # snip
  watchers: [
    pnpm: ["run", "dev", cd: Path.expand("../assets", __DIR__)]
  ]

A workaround is to call process.stdin.resume() in vite.config.ts when the dev server is to be started:

const resumeStdinPlugin: PluginOption = {
  name: "resume-stdin",
  configureServer: () => {
    // runs when the dev server is triggered, but not on other commands:
    process.stdin.resume();
    // an 'end' listener is already added in `setupSIGTERMListener` here: https://github.com/vitejs/vite/blob/main/packages/vite/src/node/utils.ts#L1537
  },
};
export default defineConfig({
  plugins: [resumeStdinPlugin(), react()],
  server: {
    open: false,
    port: 3000,
  },
  clearScreen: false,
})

Related issues:

Reproduction

https://stackblitz.com/edit/vitejs-vite-shkjhvut?file=watcher.js

Steps to reproduce

The issue can be reproduced by running this Elixir script at the root of a new vite app (pnpm create vite@latest):

# watcher.exs

# Mix.install([:phoenix])
# Phoenix.Endpoint.Watcher.watch("pnpm", ["run", "dev", cd: Path.expand("./", __DIR__)])

System.cmd("pnpm", ["run", "dev"], cd: Path.expand("./", __DIR__), into: IO.stream(:stdio, :line), stderr_to_stdout: true)

Running the Elixir script with elixir watcher.exs and stopping with ctrl+c (twice) leaves the Vite server running. Tested with Elixir 1.17.3 and 1.18.0, but I suspect it will behave the same in any Elixir version.

The issue can also be reproduced with this javascript:

# watcher.js
import { spawn } from 'child_process'

const childProcess = spawn('pnpm', ['run', 'dev'], {
  // make child process stdin non-tty (pipe), like it is with elixir's System.cmd/3
  stdio: ['pipe', 'inherit', 'inherit'],
  detached: true,
})

childProcess.on('error', (err) => {
  console.error('Failed to start process:', err)
})

childProcess.on('exit', (code) => {
  console.log(`Process exited with code ${code}`)
})

process.on('SIGINT', () => {
  console.log(
    '\nReceived SIGINT in parent. Child process will continue running.',
  )
})

process.on('SIGTERM', () => {
  childProcess.unref()
  console.log(
    '\nReceived SIGTERM in parent. Child process will continue running.',
  )
})

Stackblitz note: ctrl+c seems to behave differently there, so had to trigger an interrupt with kill -SIGINT $pid to reproduce.

System Info

❯ npx envinfo --system --npmPackages '{vite,@vitejs/*,rollup}' --binaries

  System:
    OS: macOS 15.2
    CPU: (10) arm64 Apple M1 Max
    Memory: 98.63 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.13.1 - ~/.asdf/installs/nodejs/20.13.1/bin/node
    npm: 10.5.2 - ~/.asdf/plugins/nodejs/shims/npm
    pnpm: 9.15.2 - ~/.asdf/shims/pnpm
    bun: 1.1.3 - ~/.asdf/shims/bun
    Watchman: 2024.11.04.00 - /opt/homebrew/bin/watchman
  npmPackages:
    @vitejs/plugin-react: ^4.3.4 => 4.3.4
    vite: ^6.0.5 => 6.0.6

Used Package Manager

pnpm

Logs

elixir watcher.exs (Click to expand)
❯ elixir watcher.exs

> [email protected] dev /Users/steve/src/vite-exit
> vite


  VITE v6.0.6  ready in 122 ms

  ➜  Local:   http://localhost:3000/
  ➜  Network: use --host to expose
^C
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
^C%

~/src/vite-exit main*​ 6s
❯ lsof -iTCP -sTCP:LISTEN -n -P | grep 3000
node      52063 steve   15u  IPv6 0xa5031061aa06787d      0t0  TCP [::1]:3000 (LISTEN)

~/src/vite-exit main*​
❯ kill 52063
pnpm exec node watcher.js (Click to expand)
❯ pnpm exec node watcher.js

> [email protected] dev /Users/steve/src/vite-exit
> vite


  VITE v6.0.6  ready in 136 ms

  ➜  Local:   http://localhost:3000/
  ➜  Network: use --host to expose
^C

Received SIGINT in parent. Child process will continue running.

Received SIGTERM in parent. Child process will continue running.

~/src/vite-exit main*​​ 3s
❯ lsof -iTCP -sTCP:LISTEN -n -P | grep 3000
node      55724 steve   15u  IPv6 0x6e865d767a45d615      0t0  TCP [::1]:3000 (LISTEN)

~/src/vite-exit main*​​
❯ lsof -iTCP -sTCP:LISTEN -n -P | grep 3000 | awk '{print $2}' | xargs kill
 ELIFECYCLE  Command failed with exit code 143.

Validations

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

Successfully merging a pull request may close this issue.

1 participant