1
1
import * as childProcess from 'child_process' ;
2
2
import * as path from 'path' ;
3
3
import * as readline from 'readline' ;
4
+ import { waitUntilPortState } from './ports' ;
4
5
const treeKill = require ( 'tree-kill' ) ;
5
6
const crossSpawn : typeof childProcess . spawn = require ( 'cross-spawn' ) ;
7
+ const defaultPort = 5000 ;
6
8
7
- export const defaultUrl = ' http://localhost:5000' ;
9
+ export const defaultUrl = ` http://localhost:${ defaultPort } ` ;
8
10
9
11
export enum AspNetCoreEnviroment {
10
12
development ,
@@ -50,7 +52,7 @@ export class AspNetProcess {
50
52
} ) ;
51
53
52
54
// Ensure the process isn't orphaned even if Node crashes before we're disposed
53
- process . on ( 'exit' , ( ) => this . _killProcessSync ( ) ) ;
55
+ process . on ( 'exit' , ( ) => this . _killAspNetProcess ( ) ) ;
54
56
55
57
// Also track whether it exited on its own already
56
58
this . _process . on ( 'exit' , ( ) => {
@@ -74,7 +76,7 @@ export class AspNetProcess {
74
76
75
77
public dispose ( ) : Promise < any > {
76
78
return new Promise ( ( resolve , reject ) => {
77
- this . _killProcessSync ( err => {
79
+ this . _killAspNetProcess ( err => {
78
80
if ( err ) {
79
81
reject ( err ) ;
80
82
} else {
@@ -84,11 +86,29 @@ export class AspNetProcess {
84
86
} ) ;
85
87
}
86
88
87
- private _killProcessSync ( callback ?: ( err : any ) => void ) {
89
+ private _killAspNetProcess ( callback ?: ( err : any ) => void ) {
90
+ callback = callback || ( ( ) => { } ) ;
88
91
if ( ! this . _processHasExited ) {
89
92
// It's important to kill the whole tree, because 'dotnet run' launches a separate 'dotnet exec'
90
93
// child process that would otherwise be left running
91
- treeKill ( this . _process . pid , 'SIGINT' , callback ) ;
94
+ treeKill ( this . _process . pid , 'SIGINT' , err => {
95
+ if ( err ) {
96
+ callback ( err ) ;
97
+ } else {
98
+ // It's not enough just to send a SIGINT to ASP.NET. It will stay open for a moment, completing
99
+ // any outstanding requests. We have to wait for it really to be gone before continuing, otherwise
100
+ // the next test might be unable to start because of the port still being in use.
101
+ console . log ( `Waiting until port ${ defaultPort } is closed...` ) ;
102
+ waitUntilPortState ( defaultPort , /* isOpen */ true , /* timeoutMs */ 15000 , err => {
103
+ if ( err ) {
104
+ callback ( err ) ;
105
+ } else {
106
+ console . log ( `Port ${ defaultPort } is now closed` ) ;
107
+ callback ( null ) ;
108
+ }
109
+ } ) ;
110
+ }
111
+ } ) ;
92
112
}
93
113
}
94
114
}
0 commit comments