Skip to content

Commit 64187c4

Browse files
authored
Fix panic with build error (#295)
1 parent 4612c12 commit 64187c4

File tree

2 files changed

+138
-1
lines changed

2 files changed

+138
-1
lines changed

runner/engine.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ func (e *Engine) buildRun() {
368368
}
369369
var err error
370370
if err = e.building(); err != nil {
371-
close(e.canExit)
371+
e.canExit <- true
372372
e.buildLog("failed to build, error: %s", err.Error())
373373
_ = e.writeBuildErrorLog(err.Error())
374374
if e.config.Build.StopOnError {

runner/engine_test.go

+137
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,100 @@ func TestCtrlCWhenREngineIsRunning(t *testing.T) {
286286
assert.False(t, engine.running)
287287
}
288288

289+
func TestFixCloseOfChannelAfterCtrlC(t *testing.T) {
290+
// fix https://github.com/cosmtrek/air/issues/294
291+
dir := initWithBuildFailedCode(t)
292+
293+
err := os.Chdir(dir)
294+
if err != nil {
295+
t.Fatalf("Should not be fail: %s.", err)
296+
}
297+
engine, err := NewEngine("", true)
298+
if err != nil {
299+
t.Fatalf("Should not be fail: %s.", err)
300+
}
301+
sigs := make(chan os.Signal, 1)
302+
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
303+
go func() {
304+
engine.Run()
305+
t.Logf("engine stopped")
306+
}()
307+
308+
go func() {
309+
<-sigs
310+
engine.Stop()
311+
t.Logf("engine stopped")
312+
}()
313+
// waiting for compile error
314+
time.Sleep(time.Second * 3)
315+
port, f := GetPort()
316+
f()
317+
// correct code
318+
err = generateGoCode(dir, port)
319+
if err != nil {
320+
t.Fatalf("Should not be fail: %s.", err)
321+
}
322+
323+
if err := waitingPortReady(t, port, time.Second*5); err != nil {
324+
t.Fatalf("Should not be fail: %s.", err)
325+
}
326+
327+
// ctrl + c
328+
sigs <- syscall.SIGINT
329+
time.Sleep(time.Second * 1)
330+
if err := waitingPortConnectionRefused(t, port, time.Second*10); err != nil {
331+
t.Fatalf("Should not be fail: %s.", err)
332+
}
333+
assert.False(t, engine.running)
334+
335+
}
336+
337+
func TestFixCloseOfChannelAfterTwoFailedBuild(t *testing.T) {
338+
// fix https://github.com/cosmtrek/air/issues/294
339+
// happens after two failed builds
340+
dir := initWithBuildFailedCode(t)
341+
// change dir to tmpDir
342+
err := os.Chdir(dir)
343+
if err != nil {
344+
t.Fatalf("Should not be fail: %s.", err)
345+
}
346+
engine, err := NewEngine("", true)
347+
if err != nil {
348+
t.Fatalf("Should not be fail: %s.", err)
349+
}
350+
sigs := make(chan os.Signal, 1)
351+
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
352+
go func() {
353+
engine.Run()
354+
t.Logf("engine stopped")
355+
}()
356+
357+
go func() {
358+
<-sigs
359+
engine.Stop()
360+
t.Logf("engine stopped")
361+
}()
362+
363+
// waiting for compile error
364+
time.Sleep(time.Second * 3)
365+
366+
// edit *.go file to create build error again
367+
file, err := os.OpenFile("main.go", os.O_APPEND|os.O_WRONLY, 0644)
368+
if err != nil {
369+
t.Fatalf("Should not be fail: %s.", err)
370+
}
371+
defer file.Close()
372+
_, err = file.WriteString("\n")
373+
if err != nil {
374+
t.Fatalf("Should not be fail: %s.", err)
375+
}
376+
time.Sleep(time.Second * 3)
377+
// ctrl + c
378+
sigs <- syscall.SIGINT
379+
time.Sleep(time.Second * 1)
380+
assert.False(t, engine.running)
381+
}
382+
289383
// waitingPortReady waits until the port is ready to be used.
290384
func waitingPortReady(t *testing.T, port int, timeout time.Duration) error {
291385
t.Logf("waiting port %d ready", port)
@@ -368,6 +462,49 @@ func initTestEnv(t *testing.T, port int) string {
368462
return tempDir
369463
}
370464

465+
func initWithBuildFailedCode(t *testing.T) string {
466+
tempDir := t.TempDir()
467+
t.Logf("tempDir: %s", tempDir)
468+
// generate golang code to tempdir
469+
err := generateBuildErrorGoCode(tempDir)
470+
if err != nil {
471+
t.Fatalf("Should not be fail: %s.", err)
472+
}
473+
return tempDir
474+
}
475+
476+
func generateBuildErrorGoCode(dir string) error {
477+
code := `package main
478+
// You can edit this code!
479+
// Click here and start typing.
480+
481+
func main() {
482+
Println("Hello, 世界")
483+
484+
}
485+
`
486+
file, err := os.Create(dir + "/main.go")
487+
if err != nil {
488+
return err
489+
}
490+
_, err = file.WriteString(code)
491+
492+
// generate go mod file
493+
mod := `module air.sample.com
494+
495+
go 1.17
496+
`
497+
file, err = os.Create(dir + "/go.mod")
498+
if err != nil {
499+
return err
500+
}
501+
_, err = file.WriteString(mod)
502+
if err != nil {
503+
return err
504+
}
505+
return nil
506+
}
507+
371508
// generateGoCode generates golang code to tempdir
372509
func generateGoCode(dir string, port int) error {
373510

0 commit comments

Comments
 (0)