-
Notifications
You must be signed in to change notification settings - Fork 103
Make sure that the signing of .js and .vbs files with the AzureSignToolSigner uses STA context. #881
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…olSigner uses STA context.
a71f3e7
to
4504884
Compare
|
||
// loop through all of the files here, looking for appx/eappx | ||
// mark each as being signed and strip appx | ||
await Parallel.ForEachAsync(files, async (file, state) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested the fix by signing a single .js file. The STA signing above succeeded, but this failed because it tries to sign all files on an MTA thread, which was the original problem.
This statement should sign all files that don't have a file extension in StaThreadExtensions
.
We should have test coverage.
{ | ||
internal sealed class AzureSignToolSigner : IAzureSignToolDataFormatSigner | ||
{ | ||
private static readonly string[] StaThreadExtensions = [".js", ".vbs"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comparisons should be case-insensitive.
private static readonly string[] StaThreadExtensions = [".js", ".vbs"]; | |
private static readonly HashSet<string> StaThreadExtensions = new(StringComparer.OrdinalIgnoreCase) | |
{ | |
".js", | |
".vbs" | |
}; |
return false; | ||
} | ||
|
||
private static Task<bool> RunOnStaThread(Func<Task> func) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private static Task<bool> RunOnStaThread(Func<Task> func) | |
private static Task<bool> RunOnStaThreadAsync(Func<Task> func) |
FileInfo[] staThreadFiles = [.. files.Where(file => StaThreadExtensions.Contains(file.Extension))]; | ||
foreach (FileInfo file in staThreadFiles) | ||
{ | ||
await RunOnStaThread(() => SignAsync(signer, file, options)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only works because the actual signing operation happens to execute synchronously before any await
calls. SignAsync(...)
does contain an await Thread.Delay(...)
, but it only executes on retry. With the current implementation, only the first try has any chance of success while subsequent retries are guaranteed to fail because execution will resume on the thread pool (MTA).
The proper fix involves setting a synchronization context on the STA thread so that all continuations resume on the STA thread.
https://devblogs.microsoft.com/dotnet/await-synchronizationcontext-and-console-apps/
https://devblogs.microsoft.com/dotnet/await-synchronizationcontext-and-console-apps-part-2/
Fixes #880