Skip to content
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

Fixes for big-endian systems #6204

Merged
merged 1 commit into from
Mar 11, 2021
Merged

Fixes for big-endian systems #6204

merged 1 commit into from
Mar 11, 2021

Conversation

uweigand
Copy link
Contributor

@uweigand uweigand commented Mar 1, 2021

Context

We are currently working on bringing up .NET on the IBM Z architecture (s390x-ibm-linux), which uses big-endian byte order. During that process we have run into a couple of endian-specific bugs in msbuild code.

Changes Made

  • In MSBuildNameIgnoreCaseComparer::GetHashCode, when reading pairs of characters aliased to an int, handle the single last remaining char correctly on big-endian systems.

  • In NodeProviderOutOfProcBase, byte-swap the packet length on big-endian systems.

Testing

On IBM Z, a msbuild package built with this patch successfully builds and executes a "hello world" program. We were also able to successfully bootstrap msbuild (build it with itself) on IBM Z. (This of course also requires the work-in-progress dotnet runtime port, and for the bootstrap an endian bugfix to nuget is also required.)
Also verified that "./build.sh --test" still succeeds on a little-endian (Intel) Linux system.

* In MSBuildNameIgnoreCaseComparer::GetHashCode, when reading pairs of
  characters aliased to an int, handle the single last remaing char
  correctly on big-endian systems.

* In NodeProviderOutOfProcBase, byte-swap the packet length on
  big-endian systems.
Copy link
Member

@ladipro ladipro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@uweigand
Copy link
Contributor Author

uweigand commented Mar 4, 2021

Thanks for the review! One additional comment on the NodeProviderOutOfProcBase change (which I just noticed as I was trying to backport the changes to older releases):

The packet length problem is actually quite recent, it was introduced only 4 weeks ago by this commit by @KirillOsenkov
de3b887#diff-f0e57cbf17e0f7fb207f255deb11445afccbb5c7bf0499a24b8065ff057fcdf3

Before that patch the packet length used to be in native byte order. The patch changed the sender to write the packet length always in little-endian byte order (using the BinaryWriter which always uses little-endian, and/or the new WriteInt32 routine. However, the receiver side was not changed, which caused the mismatch.

Now, once this PR is applied, that mismatch will be fixed again. However, I'm now wondering if that switch in encoding was even intentional in the first place. Could there ever be the situation where an "old" version of msbuild (using native-endian encoding) would have to communicate with a "new" version (using little-endian endian encoding)? That might still be a problem then.

uweigand referenced this pull request Mar 4, 2021
* Reduce byte array allocations when reading/writing packets

Byte arrays are a major source of LOH allocations when streaming logging events across nodes. Allocating a large MemoryStream once and then growing it as needed almost completely removes allocations for byte arrays.

This should significantly improve memory traffic during large builds.

* Write the last part of the packet synchronously on Mono.

If we use WriteAsync and don't await it, then subsequent WriteAsync may be called before the first continuation returns. If both calls share the same buffer and they overlap, we will overwrite the data in the buffer and cause junk to arrive at receiver.

* Make SendData write packets asynchronously.

This avoids blocking the main loop. Roughly equivalent to writing the packet asynchronously using fire-and-forget (BeginWrite).
@ladipro
Copy link
Member

ladipro commented Mar 4, 2021

MSBuild never communicates cross-version and the only part of the protocol we have to be careful about is the handshake where we check that the version (plus a few other things) matches. So no concerns here, we don't have to be backward or forward compatible when it comes to the actual packet exchange.

@uweigand
Copy link
Contributor Author

uweigand commented Mar 4, 2021

OK, then this patch should be all that is required to fix it again. Thanks!

@KirillOsenkov
Copy link
Member

Thanks, I didn't pay attention to endianness when I made the change. It was driven purely by the need to reduce allocations since BitConverter required a 4-byte array. In general I'll need to learn more about endianness and pay more attention to it going forward, so this is educational.

@Forgind Forgind added the merge-when-branch-open PRs that are approved, except that there is a problem that means we are not merging stuff right now. label Mar 5, 2021
@rokonec rokonec merged commit 514ceb5 into dotnet:master Mar 11, 2021
@uweigand uweigand deleted the bigendian branch May 14, 2021 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merge-when-branch-open PRs that are approved, except that there is a problem that means we are not merging stuff right now.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants