Skip to content

Commit

Permalink
fix(gatsby): properly unlock processes onExit (#26670)
Browse files Browse the repository at this point in the history
  • Loading branch information
wardpeet committed Aug 31, 2020
1 parent 93fdc09 commit c2aeded
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 24 deletions.
2 changes: 2 additions & 0 deletions packages/gatsby/package.json
Expand Up @@ -65,6 +65,7 @@
"eslint-plugin-react": "^7.20.6",
"eslint-plugin-react-hooks": "^1.7.0",
"event-source-polyfill": "^1.0.15",
"execa": "^4.0.3",
"express": "^4.17.1",
"express-graphql": "^0.9.0",
"fast-levenshtein": "^2.0.6",
Expand Down Expand Up @@ -161,6 +162,7 @@
"@types/normalize-path": "^3.0.0",
"@types/reach__router": "^1.3.5",
"@types/semver": "^7.1.0",
"@types/signal-exit": "^3.0.0",
"@types/socket.io": "^2.1.4",
"@types/string-similarity": "^3.0.0",
"@types/tmp": "^0.2.0",
Expand Down
89 changes: 65 additions & 24 deletions packages/gatsby/src/commands/develop.ts
Expand Up @@ -2,14 +2,17 @@
import path from "path"
import http from "http"
import tmp from "tmp"
import { spawn, ChildProcess } from "child_process"
import { ChildProcess } from "child_process"
import execa from "execa"
import chokidar from "chokidar"
import getRandomPort from "detect-port"
import { detectPortInUseAndPrompt } from "../utils/detect-port-in-use-and-prompt"
import socket from "socket.io"
import fs from "fs-extra"
import { isCI, slash } from "gatsby-core-utils"
import onExit from "signal-exit"
import {
isCI,
slash,
createServiceLock,
getService,
updateSiteMetadata,
Expand Down Expand Up @@ -92,12 +95,12 @@ class ControllableScript {
this.debugInfo = debugInfo
}
start(): void {
const args = []
const tmpFileName = tmp.tmpNameSync({
tmpdir: path.join(process.cwd(), `.cache`),
})
fs.outputFileSync(tmpFileName, this.script)
this.isRunning = true
const args = [tmpFileName]
// Passing --inspect isn't necessary for the child process to launch a port but it allows some editors to automatically attach
if (this.debugInfo) {
if (this.debugInfo.break) {
Expand All @@ -107,7 +110,7 @@ class ControllableScript {
}
}

this.process = spawn(`node`, args, {
this.process = execa.node(tmpFileName, args, {
env: process.env,
stdio: [`inherit`, `inherit`, `inherit`, `ipc`],
})
Expand All @@ -119,6 +122,7 @@ class ControllableScript {
if (!this.process) {
throw new Error(`Trying to stop the process before starting it`)
}

this.isRunning = false
if (signal) {
this.process.kill(signal)
Expand All @@ -136,6 +140,7 @@ class ControllableScript {
if (!this.process) {
throw new Error(`Trying to stop the process before starting it`)
}

this.process.on(`exit`, () => {
if (this.process) {
this.process.removeAllListeners()
Expand Down Expand Up @@ -371,11 +376,10 @@ module.exports = async (program: IProgram): Promise<void> => {

const files = [rootFile(`gatsby-config.js`), rootFile(`gatsby-node.js`)]
let lastConfig = requireUncached(rootFile(`gatsby-config.js`))

let watcher
let watcher: chokidar.FSWatcher = null

if (!isCI()) {
chokidar.watch(files).on(`change`, filePath => {
watcher = chokidar.watch(files).on(`change`, filePath => {
const file = path.basename(filePath)

if (file === `gatsby-config.js`) {
Expand Down Expand Up @@ -403,26 +407,63 @@ module.exports = async (program: IProgram): Promise<void> => {
developProcess.send(msg)
})

process.on(`beforeExit`, async () => {
await Promise.all([
watcher?.close(),
...unlocks.map(unlock => unlock()),
new Promise(resolve => {
statusServer.close(resolve)
}),
new Promise(resolve => {
proxy.server.close(resolve)
}),
])
})

process.on(`SIGINT`, async () => {
await developProcess.stop(`SIGINT`)
process.exit()
await shutdownServices(
{
developProcess,
unlocks,
statusServer,
proxy,
watcher,
},
`SIGINT`
)

process.exit(0)
})

process.on(`SIGTERM`, async () => {
await developProcess.stop(`SIGTERM`)
process.exit()
await shutdownServices(
{
developProcess,
unlocks,
statusServer,
proxy,
watcher,
},
`SIGTERM`
)

process.exit(0)
})

onExit((_code, signal) => {
shutdownServices(
{
developProcess,
unlocks,
statusServer,
proxy,
watcher,
},
signal as NodeJS.Signals
)
})
}
function shutdownServices(
{ statusServer, developProcess, proxy, unlocks, watcher },
signal: NodeJS.Signals
): Promise<void> {
const services = [
developProcess.stop(signal),
watcher?.close(),
new Promise(resolve => statusServer.close(resolve)),
new Promise(resolve => proxy.server.close(resolve)),
]

unlocks.forEach(unlock => {
services.push(unlock())
})

return Promise.all(services).then(() => {})
}
15 changes: 15 additions & 0 deletions yarn.lock
Expand Up @@ -9790,6 +9790,21 @@ execa@^4.0.0, execa@^4.0.2:
signal-exit "^3.0.2"
strip-final-newline "^2.0.0"

execa@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.3.tgz#0a34dabbad6d66100bd6f2c576c8669403f317f2"
integrity sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==
dependencies:
cross-spawn "^7.0.0"
get-stream "^5.0.0"
human-signals "^1.1.1"
is-stream "^2.0.0"
merge-stream "^2.0.0"
npm-run-path "^4.0.0"
onetime "^5.1.0"
signal-exit "^3.0.2"
strip-final-newline "^2.0.0"

executable@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c"
Expand Down

0 comments on commit c2aeded

Please sign in to comment.