Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 98aa2b1

Browse files
[release/10.0.1xx] Source code updates from dotnet/runtime (#2625)
[release/10.0.1xx] Source code updates from dotnet/runtime
1 parent af6cebc commit 98aa2b1

File tree

15 files changed

+2097
-1776
lines changed

15 files changed

+2097
-1776
lines changed

src/runtime/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -213,18 +213,21 @@ CreateCrashDump(
213213
char* errorMessageBuffer,
214214
int cbErrorMessageBuffer)
215215
{
216-
int pipe_descs[2];
217-
if (pipe(pipe_descs) == -1)
216+
int pipe_descs[4];
217+
if (pipe(pipe_descs) == -1 || pipe(pipe_descs + 2) == -1)
218218
{
219219
if (errorMessageBuffer != nullptr)
220220
{
221221
snprintf(errorMessageBuffer, cbErrorMessageBuffer, "Problem launching createdump: pipe() FAILED %s (%d)\n", strerror(errno), errno);
222222
}
223223
return false;
224224
}
225-
// [0] is read end, [1] is write end
226-
int parent_pipe = pipe_descs[0];
227-
int child_pipe = pipe_descs[1];
225+
// from parent (write) to child (read), used to signal prctl(PR_SET_PTRACER, childpid) is done
226+
int child_read_pipe = pipe_descs[0];
227+
int parent_write_pipe = pipe_descs[1];
228+
// from child (write) to parent (read), used to capture createdump's stderr
229+
int parent_read_pipe = pipe_descs[2];
230+
int child_write_pipe = pipe_descs[3];
228231

229232
// Fork the core dump child process.
230233
pid_t childpid = fork();
@@ -236,19 +239,34 @@ CreateCrashDump(
236239
{
237240
snprintf(errorMessageBuffer, cbErrorMessageBuffer, "Problem launching createdump: fork() FAILED %s (%d)\n", strerror(errno), errno);
238241
}
239-
close(pipe_descs[0]);
240-
close(pipe_descs[1]);
242+
for (int i = 0; i < 4; i++)
243+
{
244+
close(pipe_descs[i]);
245+
}
241246
return false;
242247
}
243248
else if (childpid == 0)
244249
{
245-
// Close the read end of the pipe, the child doesn't need it
246-
close(parent_pipe);
250+
close(parent_read_pipe);
251+
close(parent_write_pipe);
252+
253+
// Wait for prctl(PR_SET_PTRACER, childpid) in parent
254+
char buffer;
255+
int bytesRead;
256+
while((bytesRead = read(child_read_pipe, &buffer, 1)) < 0 && errno == EINTR);
257+
close(child_read_pipe);
258+
259+
if (bytesRead != 1)
260+
{
261+
fprintf(stderr, "Problem reading from createdump child_read_pipe: %s (%d)\n", strerror(errno), errno);
262+
close(child_write_pipe);
263+
exit(-1);
264+
}
247265

248266
// Only dup the child's stderr if there is error buffer
249267
if (errorMessageBuffer != nullptr)
250268
{
251-
dup2(child_pipe, STDERR_FILENO);
269+
dup2(child_write_pipe, STDERR_FILENO);
252270
}
253271
// Execute the createdump program
254272
if (execv(argv[0], (char* const *)argv) == -1)
@@ -259,6 +277,8 @@ CreateCrashDump(
259277
}
260278
else
261279
{
280+
close(child_read_pipe);
281+
close(child_write_pipe);
262282
#if HAVE_PRCTL_H && HAVE_PR_SET_PTRACER
263283
// Gives the child process permission to use /proc/<pid>/mem and ptrace
264284
if (prctl(PR_SET_PTRACER, childpid, 0, 0, 0) == -1)
@@ -270,15 +290,29 @@ CreateCrashDump(
270290
#endif
271291
}
272292
#endif // HAVE_PRCTL_H && HAVE_PR_SET_PTRACER
273-
close(child_pipe);
293+
// Signal child that prctl(PR_SET_PTRACER, childpid) is done
294+
int bytesWritten;
295+
while((bytesWritten = write(parent_write_pipe, "S", 1)) < 0 && errno == EINTR);
296+
close(parent_write_pipe);
297+
298+
if (bytesWritten != 1)
299+
{
300+
fprintf(stderr, "Problem writing to createdump parent_write_pipe: %s (%d)\n", strerror(errno), errno);
301+
close(parent_read_pipe);
302+
if (errorMessageBuffer != nullptr)
303+
{
304+
errorMessageBuffer[0] = 0;
305+
}
306+
return false;
307+
}
274308

275309
// Read createdump's stderr messages (if any)
276310
if (errorMessageBuffer != nullptr)
277311
{
278312
// Read createdump's stderr
279313
int bytesRead = 0;
280314
int count = 0;
281-
while ((count = read(parent_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) > 0)
315+
while ((count = read(parent_read_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) > 0)
282316
{
283317
bytesRead += count;
284318
}
@@ -288,7 +322,7 @@ CreateCrashDump(
288322
fputs(errorMessageBuffer, stderr);
289323
}
290324
}
291-
close(parent_pipe);
325+
close(parent_read_pipe);
292326

293327
// Parent waits until the child process is done
294328
int wstatus = 0;

src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ namespace System.Threading
1414
{
1515
public sealed partial class Thread
1616
{
17-
[ThreadStatic]
18-
private static ApartmentType t_apartmentType;
19-
2017
[ThreadStatic]
2118
private static ComState t_comState;
2219

@@ -235,14 +232,15 @@ public ApartmentState GetApartmentState()
235232
return _initialApartmentState;
236233
}
237234

238-
switch (GetCurrentApartmentType())
235+
switch (GetCurrentApartmentState())
239236
{
240-
case ApartmentType.STA:
237+
case ApartmentState.STA:
241238
return ApartmentState.STA;
242-
case ApartmentType.MTA:
239+
case ApartmentState.MTA:
243240
return ApartmentState.MTA;
244241
default:
245-
return ApartmentState.Unknown;
242+
// If COM is uninitialized on the current thread, it is assumed to be implicit MTA.
243+
return ApartmentState.MTA;
246244
}
247245
}
248246

@@ -275,14 +273,29 @@ private bool SetApartmentStateUnchecked(ApartmentState state, bool throwOnError)
275273
}
276274
else
277275
{
276+
// Compat: Setting ApartmentState to Unknown uninitializes COM
278277
UninitializeCom();
279278
}
280-
}
281279

282-
// Clear the cache and check whether new state matches the desired state
283-
t_apartmentType = ApartmentType.Unknown;
280+
// Clear the cache and check whether new state matches the desired state
281+
t_comState &= ~(ComState.STA | ComState.MTA);
284282

285-
retState = GetApartmentState();
283+
retState = GetCurrentApartmentState();
284+
}
285+
else
286+
{
287+
Debug.Assert((t_comState & ComState.MTA) != 0);
288+
retState = ApartmentState.MTA;
289+
}
290+
}
291+
292+
// Special case where we pass in Unknown and get back MTA.
293+
// Once we CoUninitialize the thread, the OS will still
294+
// report the thread as implicitly in the MTA if any
295+
// other thread in the process is CoInitialized.
296+
if ((state == ApartmentState.Unknown) && (retState == ApartmentState.MTA))
297+
{
298+
return true;
286299
}
287300

288301
if (retState != state)
@@ -316,7 +329,7 @@ private static void InitializeComForThreadPoolThread()
316329
// Process-wide COM is initialized very early before any managed code can run.
317330
// Assume it is done.
318331
// Prevent re-initialization of COM model on threadpool threads from the default one.
319-
t_comState |= ComState.Locked;
332+
t_comState |= ComState.Locked | ComState.MTA;
320333
}
321334

322335
private static void InitializeCom(ApartmentState state = ApartmentState.MTA)
@@ -396,49 +409,53 @@ internal static Thread EnsureThreadPoolThreadInitialized()
396409
public void Interrupt() { throw new PlatformNotSupportedException(); }
397410

398411
internal static bool ReentrantWaitsEnabled =>
399-
GetCurrentApartmentType() == ApartmentType.STA;
412+
GetCurrentApartmentState() == ApartmentState.STA;
400413

401-
internal static ApartmentType GetCurrentApartmentType()
414+
// Unlike the public API, this returns ApartmentState.Unknown when COM is uninitialized on the current thread
415+
internal static ApartmentState GetCurrentApartmentState()
402416
{
403-
ApartmentType currentThreadType = t_apartmentType;
404-
if (currentThreadType != ApartmentType.Unknown)
405-
return currentThreadType;
417+
if ((t_comState & (ComState.MTA | ComState.STA)) != 0)
418+
return ((t_comState & ComState.STA) != 0) ? ApartmentState.STA : ApartmentState.MTA;
406419

407420
Interop.APTTYPE aptType;
408421
Interop.APTTYPEQUALIFIER aptTypeQualifier;
409422
int result = Interop.Ole32.CoGetApartmentType(out aptType, out aptTypeQualifier);
410423

411-
ApartmentType type = ApartmentType.Unknown;
424+
ApartmentState state = ApartmentState.Unknown;
412425

413426
switch (result)
414427
{
415428
case HResults.CO_E_NOTINITIALIZED:
416-
type = ApartmentType.None;
429+
Debug.Fail("COM is not initialized");
430+
state = ApartmentState.Unknown;
417431
break;
418432

419433
case HResults.S_OK:
420434
switch (aptType)
421435
{
422436
case Interop.APTTYPE.APTTYPE_STA:
423437
case Interop.APTTYPE.APTTYPE_MAINSTA:
424-
type = ApartmentType.STA;
438+
state = ApartmentState.STA;
425439
break;
426440

427441
case Interop.APTTYPE.APTTYPE_MTA:
428-
type = ApartmentType.MTA;
442+
state = ApartmentState.MTA;
429443
break;
430444

431445
case Interop.APTTYPE.APTTYPE_NA:
432446
switch (aptTypeQualifier)
433447
{
434448
case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_MTA:
449+
state = ApartmentState.MTA;
450+
break;
451+
435452
case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA:
436-
type = ApartmentType.MTA;
453+
state = ApartmentState.Unknown;
437454
break;
438455

439456
case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_STA:
440457
case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_MAINSTA:
441-
type = ApartmentType.STA;
458+
state = ApartmentState.STA;
442459
break;
443460

444461
default:
@@ -454,24 +471,18 @@ internal static ApartmentType GetCurrentApartmentType()
454471
break;
455472
}
456473

457-
if (type != ApartmentType.Unknown)
458-
t_apartmentType = type;
459-
return type;
460-
}
461-
462-
internal enum ApartmentType : byte
463-
{
464-
Unknown = 0,
465-
None,
466-
STA,
467-
MTA
474+
if (state != ApartmentState.Unknown)
475+
t_comState |= (state == ApartmentState.STA) ? ComState.STA : ComState.MTA;
476+
return state;
468477
}
469478

470479
[Flags]
471480
internal enum ComState : byte
472481
{
473482
InitializedByUs = 1,
474483
Locked = 2,
484+
MTA = 4,
485+
STA = 8
475486
}
476487
}
477488
}

0 commit comments

Comments
 (0)