@@ -71,6 +71,7 @@ runInEachFileSystem(() => {
71
71
}
72
72
return lockFileContents ;
73
73
} ) ;
74
+ spyOn ( process , 'kill' ) . and . returnValue ( ) ;
74
75
75
76
const promise = locker . lock ( async ( ) => log . push ( 'fn()' ) ) ;
76
77
// The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
@@ -80,6 +81,7 @@ runInEachFileSystem(() => {
80
81
`(If you are sure no ngcc process is running then you should delete the lock-file at ${
81
82
lockFile . path } .)`
82
83
] ] ) ;
84
+ expect ( process . kill ) . toHaveBeenCalledWith ( 188 , 0 ) ;
83
85
84
86
lockFileContents = null ;
85
87
// The lock-file has been removed, so we can create our own lock-file, call `fn()` and then
@@ -88,6 +90,47 @@ runInEachFileSystem(() => {
88
90
expect ( log ) . toEqual ( [ 'write()' , 'read() => 188' , 'write()' , 'fn()' , 'remove()' ] ) ;
89
91
} ) ;
90
92
93
+ it ( 'should fail fast when waiting on a dead process' , async ( ) => {
94
+ const fs = getFileSystem ( ) ;
95
+ const log : string [ ] = [ ] ;
96
+ const lockFile = new MockLockFile ( fs , log ) ;
97
+ const logger = new MockLogger ( ) ;
98
+ const locker = new AsyncLocker ( lockFile , logger , 100 , 10 ) ;
99
+
100
+ let lockFileContents : string | null = '188' ;
101
+ spyOn ( lockFile , 'write' ) . and . callFake ( ( ) => {
102
+ log . push ( 'write()' ) ;
103
+ if ( lockFileContents ) {
104
+ throw { code : 'EEXIST' } ;
105
+ }
106
+ } ) ;
107
+ spyOn ( lockFile , 'read' ) . and . callFake ( ( ) => {
108
+ log . push ( 'read() => ' + lockFileContents ) ;
109
+ if ( lockFileContents === null ) {
110
+ throw { code : 'ENOENT' } ;
111
+ }
112
+ return lockFileContents ;
113
+ } ) ;
114
+ spyOn ( process , 'kill' ) . and . callFake ( ( ) => {
115
+ throw { code : 'ESRCH' } ;
116
+ } ) ;
117
+
118
+ const promise = locker . lock ( async ( ) => log . push ( 'fn()' ) ) ;
119
+ // The lock has already failed so no `fn()` in the log.
120
+ expect ( log ) . toEqual ( [ 'write()' , 'read() => 188' , 'write()' , 'read() => 188' ] ) ;
121
+ expect ( logger . logs . info ) . toEqual ( [ ] ) ;
122
+ expect ( process . kill ) . toHaveBeenCalledWith ( 188 , 0 ) ;
123
+ // Check that a missing process errors out.
124
+ let error : Error ;
125
+ await promise . catch ( e => error = e ) ;
126
+ expect ( log ) . toEqual ( [ 'write()' , 'read() => 188' , 'write()' , 'read() => 188' ] ) ;
127
+ expect ( error ! . message )
128
+ . toEqual (
129
+ `Lock found, but no process with PID 188 seems to be running.\n` +
130
+ `(If you are sure no ngcc process is running then you should delete the lock-file at ${
131
+ lockFile . path } .)`) ;
132
+ } ) ;
133
+
91
134
it ( 'should extend the retry timeout if the other process locking the file changes' , async ( ) => {
92
135
const fs = getFileSystem ( ) ;
93
136
const log : string [ ] = [ ] ;
@@ -109,6 +152,7 @@ runInEachFileSystem(() => {
109
152
}
110
153
return lockFileContents ;
111
154
} ) ;
155
+ spyOn ( process , 'kill' ) . and . returnValue ( ) ;
112
156
113
157
const promise = locker . lock ( async ( ) => log . push ( 'fn()' ) ) ;
114
158
// The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
@@ -118,6 +162,7 @@ runInEachFileSystem(() => {
118
162
`(If you are sure no ngcc process is running then you should delete the lock-file at ${
119
163
lockFile . path } .)`
120
164
] ] ) ;
165
+ expect ( process . kill ) . toHaveBeenCalledWith ( 188 , 0 ) ;
121
166
122
167
lockFileContents = '444' ;
123
168
// The lock-file has been taken over by another process - wait for the next attempt
@@ -131,6 +176,7 @@ runInEachFileSystem(() => {
131
176
`(If you are sure no ngcc process is running then you should delete the lock-file at ${
132
177
lockFile . path } .)`]
133
178
] ) ;
179
+ expect ( process . kill ) . toHaveBeenCalledWith ( 444 , 0 ) ;
134
180
135
181
lockFileContents = null ;
136
182
// The lock-file has been removed, so we can create our own lock-file, call `fn()` and
@@ -163,11 +209,13 @@ runInEachFileSystem(() => {
163
209
}
164
210
return lockFileContents ;
165
211
} ) ;
212
+ spyOn ( process , 'kill' ) . and . returnValue ( ) ;
166
213
167
214
const promise = locker . lock ( async ( ) => log . push ( 'fn()' ) ) ;
168
215
169
216
// The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
170
217
expect ( log ) . toEqual ( [ 'write()' , 'read() => 188' ] ) ;
218
+ expect ( process . kill ) . toHaveBeenCalledWith ( 188 , 0 ) ;
171
219
// Do not remove the lock-file and let the call to `lock()` timeout.
172
220
let error : Error ;
173
221
await promise . catch ( e => error = e ) ;
0 commit comments