Skip to content

Commit

Permalink
add a further guard against #643
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Feb 1, 2021
1 parent d0a87e4 commit 76eafee
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 3 deletions.
18 changes: 17 additions & 1 deletion cmd/esbuild/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"regexp"
"runtime/debug"
"sync"
"time"

"github.com/evanw/esbuild/internal/cli_helpers"
"github.com/evanw/esbuild/internal/config"
Expand Down Expand Up @@ -64,7 +65,9 @@ func runService() {
if !ok {
break // No more packets
}
os.Stdout.Write(packet.bytes)
if _, err := os.Stdout.Write(packet.bytes); err != nil {
os.Exit(1) // I/O error
}

// Only signal that this request is done when it has actually been written
if packet.refCount != 0 {
Expand All @@ -76,6 +79,19 @@ func runService() {
// The protocol always starts with the version
os.Stdout.Write(append(writeUint32(nil, uint32(len(esbuildVersion))), esbuildVersion...))

// Periodically ping the host even when we're idle. This will catch cases
// where the host has disappeared and will never send us anything else but
// we incorrectly think we are still needed. In that case we will now try
// to write to stdout and fail, and then know that we should exit.
go func() {
for {
time.Sleep(1 * time.Second)
service.sendRequest(map[string]interface{}{
"command": "ping",
})
}
}()

for {
// Read more data from stdin
n, err := os.Stdin.Read(buffer)
Expand Down
6 changes: 6 additions & 0 deletions lib/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ export function createChannel(streamIn: StreamIn): StreamOut {
};

type RequestType =
| protocol.PingRequest
| protocol.OnResolveRequest
| protocol.OnLoadRequest
| protocol.OnRequestRequest
Expand All @@ -456,6 +457,11 @@ export function createChannel(streamIn: StreamIn): StreamOut {
// Catch exceptions in the code below so they get passed to the caller
try {
switch (request.command) {
case 'ping': {
sendResponse(id, {});
break;
}

case 'resolve': {
let callback = pluginCallbacks.get(request.key);
sendResponse(id, await callback!(request) as any);
Expand Down
4 changes: 4 additions & 0 deletions lib/stdio_protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export interface BuildOutputFile {
contents: Uint8Array;
}

export interface PingRequest {
command: 'ping';
}

export interface RebuildRequest {
command: 'rebuild';
rebuildID: number;
Expand Down
3 changes: 1 addition & 2 deletions scripts/browser/browser-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,9 @@ async function main() {
}

for (let key in pages) {
promises.push(runPage(key))
await runPage(key)
}

await Promise.all(promises)
await browser.close()
server.close()

Expand Down

0 comments on commit 76eafee

Please sign in to comment.