@@ -20,6 +20,7 @@ internal sealed class TestApplication(
20
20
TerminalTestReporter output ,
21
21
Action < CommandLineOptionMessages > onHelpRequested ) : IDisposable
22
22
{
23
+ private readonly Lock _requestLock = new ( ) ;
23
24
private readonly BuildOptions _buildOptions = buildOptions ;
24
25
private readonly Action < CommandLineOptionMessages > _onHelpRequested = onHelpRequested ;
25
26
private readonly TestApplicationHandler _handler = new ( output , module , testOptions ) ;
@@ -199,63 +200,69 @@ private async Task WaitConnectionAsync(CancellationToken token)
199
200
200
201
private Task < IResponse > OnRequest ( NamedPipeServer server , IRequest request )
201
202
{
202
- try
203
+ // We need to lock as we might be called concurrently when test app child processes all communicate with us.
204
+ // For example, in a case of a sharding extension, we could get test result messages concurrently.
205
+ // To be the most safe, we lock the whole OnRequest.
206
+ lock ( _requestLock )
203
207
{
204
- switch ( request )
208
+ try
205
209
{
206
- case HandshakeMessage handshakeMessage :
207
- _handshakes . Add ( server , handshakeMessage ) ;
208
- string negotiatedVersion = GetSupportedProtocolVersion ( handshakeMessage ) ;
209
- OnHandshakeMessage ( handshakeMessage , negotiatedVersion . Length > 0 ) ;
210
- return Task . FromResult ( ( IResponse ) CreateHandshakeMessage ( negotiatedVersion ) ) ;
211
-
212
- case CommandLineOptionMessages commandLineOptionMessages :
213
- OnCommandLineOptionMessages ( commandLineOptionMessages ) ;
214
- break ;
215
-
216
- case DiscoveredTestMessages discoveredTestMessages :
217
- OnDiscoveredTestMessages ( discoveredTestMessages ) ;
218
- break ;
219
-
220
- case TestResultMessages testResultMessages :
221
- OnTestResultMessages ( testResultMessages ) ;
222
- break ;
223
-
224
- case FileArtifactMessages fileArtifactMessages :
225
- OnFileArtifactMessages ( fileArtifactMessages ) ;
226
- break ;
227
-
228
- case TestSessionEvent sessionEvent :
229
- OnSessionEvent ( sessionEvent ) ;
230
- break ;
231
-
232
- // If we don't recognize the message, log and skip it
233
- case UnknownMessage unknownMessage :
234
- Logger . LogTrace ( $ "Request '{ request . GetType ( ) } ' with Serializer ID = { unknownMessage . SerializerId } is unsupported.") ;
235
- return Task . FromResult ( ( IResponse ) VoidResponse . CachedInstance ) ;
236
-
237
- default :
238
- // If it doesn't match any of the above, throw an exception
239
- throw new NotSupportedException ( string . Format ( CliCommandStrings . CmdUnsupportedMessageRequestTypeException , request . GetType ( ) ) ) ;
210
+ switch ( request )
211
+ {
212
+ case HandshakeMessage handshakeMessage :
213
+ _handshakes . Add ( server , handshakeMessage ) ;
214
+ string negotiatedVersion = GetSupportedProtocolVersion ( handshakeMessage ) ;
215
+ OnHandshakeMessage ( handshakeMessage , negotiatedVersion . Length > 0 ) ;
216
+ return Task . FromResult ( ( IResponse ) CreateHandshakeMessage ( negotiatedVersion ) ) ;
217
+
218
+ case CommandLineOptionMessages commandLineOptionMessages :
219
+ OnCommandLineOptionMessages ( commandLineOptionMessages ) ;
220
+ break ;
221
+
222
+ case DiscoveredTestMessages discoveredTestMessages :
223
+ OnDiscoveredTestMessages ( discoveredTestMessages ) ;
224
+ break ;
225
+
226
+ case TestResultMessages testResultMessages :
227
+ OnTestResultMessages ( testResultMessages ) ;
228
+ break ;
229
+
230
+ case FileArtifactMessages fileArtifactMessages :
231
+ OnFileArtifactMessages ( fileArtifactMessages ) ;
232
+ break ;
233
+
234
+ case TestSessionEvent sessionEvent :
235
+ OnSessionEvent ( sessionEvent ) ;
236
+ break ;
237
+
238
+ // If we don't recognize the message, log and skip it
239
+ case UnknownMessage unknownMessage :
240
+ Logger . LogTrace ( $ "Request '{ request . GetType ( ) } ' with Serializer ID = { unknownMessage . SerializerId } is unsupported.") ;
241
+ return Task . FromResult ( ( IResponse ) VoidResponse . CachedInstance ) ;
242
+
243
+ default :
244
+ // If it doesn't match any of the above, throw an exception
245
+ throw new NotSupportedException ( string . Format ( CliCommandStrings . CmdUnsupportedMessageRequestTypeException , request . GetType ( ) ) ) ;
246
+ }
247
+ }
248
+ catch ( Exception ex )
249
+ {
250
+ // BE CAREFUL:
251
+ // When handling some of the messages, we may throw an exception in unexpected state.
252
+ // (e.g, OnSessionEvent may throw if we receive TestSessionEnd without TestSessionStart).
253
+ // (or if we receive help-related messages when not in help mode)
254
+ // In that case, we FailFast.
255
+ // The lack of FailFast *might* have unintended consequences, such as breaking the internal loop of pipe server.
256
+ // In that case, maybe MTP app will continue waiting for response, but we don't send the response and are waiting for
257
+ // MTP app process exit (which doesn't happen).
258
+ // So, we explicitly FailFast here.
259
+ string exAsString = ex . ToString ( ) ;
260
+ Logger . LogTrace ( exAsString ) ;
261
+ Environment . FailFast ( exAsString ) ;
240
262
}
241
- }
242
- catch ( Exception ex )
243
- {
244
- // BE CAREFUL:
245
- // When handling some of the messages, we may throw an exception in unexpected state.
246
- // (e.g, OnSessionEvent may throw if we receive TestSessionEnd without TestSessionStart).
247
- // (or if we receive help-related messages when not in help mode)
248
- // In that case, we FailFast.
249
- // The lack of FailFast *might* have unintended consequences, such as breaking the internal loop of pipe server.
250
- // In that case, maybe MTP app will continue waiting for response, but we don't send the response and are waiting for
251
- // MTP app process exit (which doesn't happen).
252
- // So, we explicitly FailFast here.
253
- string exAsString = ex . ToString ( ) ;
254
- Logger . LogTrace ( exAsString ) ;
255
- Environment . FailFast ( exAsString ) ;
256
- }
257
263
258
- return Task . FromResult ( ( IResponse ) VoidResponse . CachedInstance ) ;
264
+ return Task . FromResult ( ( IResponse ) VoidResponse . CachedInstance ) ;
265
+ }
259
266
}
260
267
261
268
private static string GetSupportedProtocolVersion ( HandshakeMessage handshakeMessage )
0 commit comments