@@ -6,47 +6,47 @@ var os = require("os");
6
6
const child_process = require ( "child_process" ) ;
7
7
const rescript_exe = require ( "./bin_path" ) . rescript_exe ;
8
8
9
- /**
10
- * @typedef {Object } ProjectFiles
11
- * @property {Array<string> } dirs
12
- * @property {Array<string> } generated
13
- */
14
-
15
- /**
16
- * @typedef {Object } WatcherRef
17
- * @property {string } dir
18
- * @property {fs.FSWatcher } watcher
19
- */
20
-
21
9
const cwd = process . cwd ( ) ;
22
10
const lockFileName = path . join ( cwd , ".bsb.lock" ) ;
23
11
24
- let isBuilding = false ;
12
+ /**
13
+ * @type {child_process.ChildProcess | null }
14
+ */
15
+ let ownerProcess = null ;
25
16
function releaseBuild ( ) {
26
- if ( isBuilding ) {
17
+ if ( ownerProcess ) {
27
18
try {
19
+ ownerProcess . kill ( ) ;
28
20
fs . unlinkSync ( lockFileName ) ;
29
- } catch ( err ) { }
30
- isBuilding = false ;
21
+ } catch { }
22
+ ownerProcess = null ;
31
23
}
32
24
}
33
25
34
- // We use [~perm:0o664] rather than our usual default perms, [0o666], because
35
- // lock files shouldn't rely on the umask to disallow tampering by other.
36
- function acquireBuild ( ) {
37
- if ( isBuilding ) {
38
- return false ;
26
+ /**
27
+ * We use [~perm:0o664] rather than our usual default perms, [0o666], because
28
+ * lock files shouldn't rely on the umask to disallow tampering by other.
29
+ *
30
+ * @param {Array<string> } args
31
+ */
32
+ function acquireBuild ( args ) {
33
+ if ( ownerProcess ) {
34
+ return null ;
39
35
} else {
40
36
try {
41
- const fid = fs . openSync ( lockFileName , "wx" , 0o664 ) ;
42
- fs . closeSync ( fid ) ;
43
- isBuilding = true ;
37
+ ownerProcess = child_process . spawn ( rescript_exe , args , {
38
+ stdio : "inherit" ,
39
+ } ) ;
40
+ fs . writeFileSync ( lockFileName , ownerProcess . pid . toString ( ) , {
41
+ encoding : "utf8" ,
42
+ mode : 0o664 ,
43
+ } ) ;
44
44
} catch ( err ) {
45
45
if ( err . code === "EEXIST" ) {
46
46
console . warn ( lockFileName , "already exists, try later" ) ;
47
47
} else console . log ( err ) ;
48
48
}
49
- return isBuilding ;
49
+ return ownerProcess ;
50
50
}
51
51
}
52
52
@@ -55,23 +55,17 @@ function acquireBuild() {
55
55
* @param {(code: number) => void } [maybeOnClose]
56
56
*/
57
57
function delegate ( args , maybeOnClose ) {
58
- if ( acquireBuild ( ) ) {
59
- /**
60
- * @type {child_process.ChildProcess }
61
- */
62
- const p = child_process . spawn ( rescript_exe , args , {
63
- stdio : "inherit" ,
64
- } ) ;
65
-
66
- p . on ( "error" , e => {
58
+ let p ;
59
+ if ( ( p = acquireBuild ( args ) ) ) {
60
+ p . once ( "error" , e => {
67
61
console . error ( String ( e ) ) ;
68
62
releaseBuild ( ) ;
69
63
process . exit ( 2 ) ;
70
64
} ) ;
71
65
72
66
// The 'close' event will always emit after 'exit' was already emitted, or
73
67
// 'error' if the child failed to spawn.
74
- p . on ( "close" , code => {
68
+ p . once ( "close" , code => {
75
69
releaseBuild ( ) ;
76
70
const exitCode = code === null ? 1 : code ;
77
71
if ( maybeOnClose ) {
@@ -376,7 +370,7 @@ Please pick a different one using the \`-ws [host:]port\` flag from bsb.`);
376
370
} else {
377
371
dlog ( `Rebuilding since ${ reasonsToRebuild } ` ) ;
378
372
}
379
- if ( acquireBuild ( ) ) {
373
+ if ( acquireBuild ( args ) ) {
380
374
logStartCompiling ( ) ;
381
375
child_process
382
376
. spawn ( rescript_exe , rescriptWatchBuildArgs , {
0 commit comments