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

Update OS version detection to get version directly from Windows #2239

Merged
merged 6 commits into from
Aug 12, 2023

Conversation

JamesNK
Copy link
Member

@JamesNK JamesNK commented Aug 10, 2023

Addresses https://github.com/grpc/grpc-dotnet/pull/2229/files#r1288695799

Environment.OSVersion.Version is a problem on older versions of .NET. It reports the OS based on the compatibility settings of an app, not the real version. This isn't a problem in our unit tests because there isn't a compatibility setting, but will be a problem when Grpc.Net.Client is used in a real-world client app.

For example, an app is installed on Windows 11 but is configured to be compatible with Windows 10. The version reported is Windows 10.

Fix this by getting the correct version directly from Windows. There are two options for doing this: PInvoke Windows API or read from the registry. Using PInvoke as it's simpler.

This issue is fixed in later versions of .NET (5+). Continue to use Environment.OSVersion.Version in .NET 6 and later.

@JamesNK JamesNK force-pushed the jamesnk/pinvoke-windows-version branch from ae98344 to d649030 Compare August 11, 2023 01:12
Copy link
Contributor

@jtattermusch jtattermusch left a comment

Choose a reason for hiding this comment

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

Added a comment

There's also a test failure:

Failed DetectWindowsVersion_Windows_MatchesEnvironment [1 ms]
  Error Message:
   Invalid platform name: Windows

src/Grpc.Net.Client/Internal/NtDll.cs Show resolved Hide resolved
@jtattermusch
Copy link
Contributor

@JamesNK @jskeet since the correct way of getting the OSVersion (needed for evaluating WinHttpHandler compatibility) is getting much more complicated than simply calling Environment.OSVersion.Version, we should revisit the idea of Grpc.Net.Client providing some kind of API to tell us about the WinHttpHandler degree of support on the current system.
FWIW The API can be "unofficial / experts only", but it should be stable nevertheless.
Would it be acceptable to have an API that can only be accessed via reflection (i.e. not publicly exposed) but would have stability guarantees? Grpc.Net.Client needs to contain the detection code anyway and it would be easier for everyone if the detection mechanism would be same for everyone who uses it and also lived in a codebase that has microsoft engineers as maintainers. As you can see, the code we currently have is borderline a hack that that should be only attempted by those who can easily consult its correctness with area experts.

@jskeet
Copy link

jskeet commented Aug 11, 2023

I'd really prefer not to require reflection to access this - I'm happy with anything public even with a scary sounding "don't use this unless you're absolutely sure you need to" name. But having said that, I'd far rather require reflection than not have it at all, of course :)

@JamesNK
Copy link
Member Author

JamesNK commented Aug 11, 2023

Grpc.Net.Client providing some kind of API to tell us about the WinHttpHandler degree of support on the current system.
FWIW The API can be "unofficial / experts only", but it should be stable nevertheless.

I don't think it should be in the Grpc.Net.Client package. I don't like the idea of encouraging private reflection.

It could be in an unofficial community package. Or even just a gist. Requiring PInvoke adds to the complexity, but it can still be encapsulated in one file with less than 100 lines.

@jtattermusch
Copy link
Contributor

Grpc.Net.Client providing some kind of API to tell us about the WinHttpHandler degree of support on the current system.
FWIW The API can be "unofficial / experts only", but it should be stable nevertheless.

I don't think it should be in the Grpc.Net.Client package. I don't like the idea of encouraging private reflection.

It could be in an unofficial community package. Or even just a gist. Requiring PInvoke adds to the complexity, but it can still be encapsulated in one file with less than 100 lines.

Regardless of the solution if feels important that there is an authoritative version of the windows version detection code, ideally also together with the logic that translates windows version into its semantic meaning ("full support", "partial support", "no support") for the purposes of using WinHttpHandler. This authoritative version should be maintained by grpc-dotnet team and it should be actually used by Grpc.Net.Client and it needs to be easy to use it in other projects (regardless whether the solution is "use this nuget" or "copy this .cs file into your project and we promise it will work")

Possible solution 1:

  • all the logic required is in a single .cs file that lives in Grpc.Net.Client and the file level comment encourages downstream projects to actually copy the file verbatim (while we make some effort to make sure it actually works) and keep the copy of that file in sync with the original (if there are ever any changes).
  • IMHO this solution feels dirty and adhoc.

Possible solution 2:

  • Create a nuget package with windows version detection code and the related logic for its winhttphandler semantics.
    Grpc.Net.Client will depend on this package and use its logic as needed when targetFramework == net462 (if one wants to force using WinHttpHandler on NET 5+, they can do it but it's their responsibility to ensure that works). Client libraries can depend on the nuget package as well and make sure their detection logic is always consistent with whatever Grpc.Net.Client does.
  • The package could be named sth like Grpc.Net.Client.WinHttpHandler.PlatformDetection

Copy link
Contributor

@mgravell mgravell left a comment

Choose a reason for hiding this comment

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

I'm fine with the P/Invoke option, but please properly consider the other perspectives / approaches suggested

@JamesNK
Copy link
Member Author

JamesNK commented Aug 11, 2023

  • Create a nuget package with windows version detection code and the related logic for its winhttphandler semantics.
    Grpc.Net.Client will depend on this package and use its logic as needed when targetFramework == net462 (if one wants to force using WinHttpHandler on NET 5+, they can do it but it's their responsibility to ensure that works). Client libraries can depend on the nuget package as well and make sure their detection logic is always consistent with whatever Grpc.Net.Client does.
  • The package could be named sth like Grpc.Net.Client.WinHttpHandler.PlatformDetection

I like to limit to the minimum number of NuGet dependencies possible. Including 100 lines of code in Grpc.Net.Client is a better alternative than the extra effort and overhead of an extra NuGet package and dependency.

Remember that detection is built into Grpc.Net.Client. I just don't think many people also want the ability to check for this manually. If they do, then provide them with a 100-line helper class. Go with an ad-hoc approach until it is shown that more people want this feature and the ad-hoc approach has problems.

@JamesNK
Copy link
Member Author

JamesNK commented Aug 11, 2023

I created an issue for a creating a sample that includes detection code: #2242

@JamesNK JamesNK merged commit 22a9549 into grpc:master Aug 12, 2023
2 checks passed
@JamesNK JamesNK deleted the jamesnk/pinvoke-windows-version branch August 12, 2023 00:17
JamesNK added a commit to JamesNK/grpc-dotnet that referenced this pull request Aug 12, 2023
jtattermusch pushed a commit that referenced this pull request Aug 16, 2023
* Validate Windows version when using WinHttpHandler (#2229)

* Improve comment in GrpcChannel for WinHttpHandler + OS validation (#2237)

* Update OS version detection to get version directly from Windows (#2239)
oguzhand95 referenced this pull request in cerbos/cerbos-sdk-net Sep 11, 2023
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [Google.Protobuf](https://togithub.com/protocolbuffers/protobuf) |
nuget | patch | `3.24.2` -> `3.24.3` |
| [Grpc.Net.Client](https://togithub.com/grpc/grpc-dotnet) | nuget |
minor | `2.56.0` -> `2.57.0` |
| [Testcontainers](https://dotnet.testcontainers.org/)
([source](https://togithub.com/testcontainers/testcontainers-dotnet)) |
nuget | minor | `3.4.0` -> `3.5.0` |

---

### Release Notes

<details>
<summary>protocolbuffers/protobuf (Google.Protobuf)</summary>

###
[`v3.24.3`](https://togithub.com/protocolbuffers/protobuf/compare/v3.24.2...v3.24.3)

</details>

<details>
<summary>grpc/grpc-dotnet (Grpc.Net.Client)</summary>

###
[`v2.57.0`](https://togithub.com/grpc/grpc-dotnet/releases/tag/v2.57.0)

#### What's Changed

- Start 2.57.x development cycle by
[@&#8203;jtattermusch](https://togithub.com/jtattermusch) in
[https://github.com/grpc/grpc-dotnet/pull/2227](https://togithub.com/grpc/grpc-dotnet/pull/2227)
- Validate Windows version when using WinHttpHandler by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2229](https://togithub.com/grpc/grpc-dotnet/pull/2229)
- Support infinite idle connection timeout values by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2231](https://togithub.com/grpc/grpc-dotnet/pull/2231)
- Improve BalancerAttributes debugging by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2235](https://togithub.com/grpc/grpc-dotnet/pull/2235)
- Update Grpc.Net.Client to remove ValueTask usage by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2222](https://togithub.com/grpc/grpc-dotnet/pull/2222)
- Update Newtonsoft.Json to 13.0.3 by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2219](https://togithub.com/grpc/grpc-dotnet/pull/2219)
- Consistently don't log message errors on cancellation by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2221](https://togithub.com/grpc/grpc-dotnet/pull/2221)
- Fix load balancing flaky test by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2223](https://togithub.com/grpc/grpc-dotnet/pull/2223)
- Improve comment in GrpcChannel for WinHttpHandler + OS validation by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2237](https://togithub.com/grpc/grpc-dotnet/pull/2237)
- Update OS version detection to get version directly from Windows by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2239](https://togithub.com/grpc/grpc-dotnet/pull/2239)
- Update implementation_comparison.md by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2240](https://togithub.com/grpc/grpc-dotnet/pull/2240)
- Update to use .NET 8 by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2021](https://togithub.com/grpc/grpc-dotnet/pull/2021)
- Bump semver from 6.3.0 to 6.3.1 in
/testassets/InteropTestsGrpcWebWebsite/Tests by
[@&#8203;dependabot](https://togithub.com/dependabot) in
[https://github.com/grpc/grpc-dotnet/pull/2243](https://togithub.com/grpc/grpc-dotnet/pull/2243)
- Force yielding after awaiting CallTask to avoid holding onto locks by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2245](https://togithub.com/grpc/grpc-dotnet/pull/2245)
- Update Grpc.Net.Client to use ActivitySource by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2244](https://togithub.com/grpc/grpc-dotnet/pull/2244)
- Clear IAsyncStreamReader<T>.Current value before reading next value by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2248](https://togithub.com/grpc/grpc-dotnet/pull/2248)
- Upgrade QpsWorker to net8 by
[@&#8203;jtattermusch](https://togithub.com/jtattermusch) in
[https://github.com/grpc/grpc-dotnet/pull/2250](https://togithub.com/grpc/grpc-dotnet/pull/2250)
- Change subchannel ID to include a channel ID by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2253](https://togithub.com/grpc/grpc-dotnet/pull/2253)
- Update Grpc.Tools dependency to 2.57.0 by
[@&#8203;jtattermusch](https://togithub.com/jtattermusch) in
[https://github.com/grpc/grpc-dotnet/pull/2257](https://togithub.com/grpc/grpc-dotnet/pull/2257)
- Add transport status to subchannel picked log by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2261](https://togithub.com/grpc/grpc-dotnet/pull/2261)
- Reduce logger allocations by not using generic CreateLogger by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2256](https://togithub.com/grpc/grpc-dotnet/pull/2256)
- Update call debugger display to show status code by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2259](https://togithub.com/grpc/grpc-dotnet/pull/2259)
- Log socket lifetime when closing unusable sockets by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2258](https://togithub.com/grpc/grpc-dotnet/pull/2258)
- Fix unobserved exceptions with retries by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2255](https://togithub.com/grpc/grpc-dotnet/pull/2255)
- Change subchannel BalancerAddress when attributes change by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2228](https://togithub.com/grpc/grpc-dotnet/pull/2228)
- Fix connection bugs from BalancerAddress changes by
[@&#8203;JamesNK](https://togithub.com/JamesNK) in
[https://github.com/grpc/grpc-dotnet/pull/2265](https://togithub.com/grpc/grpc-dotnet/pull/2265)
- \[v2.57.x] Update version to 2.57.0-pre1 by
[@&#8203;jtattermusch](https://togithub.com/jtattermusch) in
[https://github.com/grpc/grpc-dotnet/pull/2266](https://togithub.com/grpc/grpc-dotnet/pull/2266)
- \[2.57.x] Update version to 2.57.0 by
[@&#8203;jtattermusch](https://togithub.com/jtattermusch) in
[https://github.com/grpc/grpc-dotnet/pull/2272](https://togithub.com/grpc/grpc-dotnet/pull/2272)

**Full Changelog**:
grpc/grpc-dotnet@v2.56.0...v2.57.0

</details>

<details>
<summary>testcontainers/testcontainers-dotnet (Testcontainers)</summary>

###
[`v3.5.0`](https://togithub.com/testcontainers/testcontainers-dotnet/releases/tag/3.5.0)

[Compare
Source](https://togithub.com/testcontainers/testcontainers-dotnet/compare/3.4.0...3.5.0)

### What's Changed

#### 🚀 Features

- feat: Allow MongoDb module configuration without credentials
([#&#8203;983](https://togithub.com/testcontainers/testcontainers-dotnet/issues/983))
[@&#8203;the-avid-engineer](https://togithub.com/the-avid-engineer)
- feat: Add support for RSA private key (RsaPrivateCrtKeyParameters) TLS
authentication with protected Docker daemon sockets
([#&#8203;978](https://togithub.com/testcontainers/testcontainers-dotnet/issues/978))
[@&#8203;zuntio](https://togithub.com/zuntio)
- feat: Add InfluxDb module
([#&#8203;975](https://togithub.com/testcontainers/testcontainers-dotnet/issues/975))
[@&#8203;MelomanG](https://togithub.com/MelomanG)

#### 🐛 Bug Fixes

- fix: Do not pre pull Dockerfile build stages that do not correspond to
base images
([#&#8203;979](https://togithub.com/testcontainers/testcontainers-dotnet/issues/979))
[@&#8203;HofmeisterAn](https://togithub.com/HofmeisterAn)

#### 📖 Documentation

- docs: Add documentation on enabling debug log messages for the default
logger
([#&#8203;991](https://togithub.com/testcontainers/testcontainers-dotnet/issues/991))
[@&#8203;HofmeisterAn](https://togithub.com/HofmeisterAn)
- docs: Add global Testcontainers header
([#&#8203;967](https://togithub.com/testcontainers/testcontainers-dotnet/issues/967))
[@&#8203;leocross](https://togithub.com/leocross)

#### 🧹 Housekeeping

- chore: Improve error message when Docker is not running
([#&#8203;987](https://togithub.com/testcontainers/testcontainers-dotnet/issues/987))
[@&#8203;0xced](https://togithub.com/0xced)
- chore: Update BouncyCastle.Cryptography to 2.2.1 (previous
Portable.BouncyCastle)
([#&#8203;985](https://togithub.com/testcontainers/testcontainers-dotnet/issues/985))
[@&#8203;jcmrva](https://togithub.com/jcmrva)
- chore: Add User-Agent HTTP header to Docker.DotNet client
([#&#8203;970](https://togithub.com/testcontainers/testcontainers-dotnet/issues/970))
[@&#8203;eddumelendez](https://togithub.com/eddumelendez)
- chore: Remove `CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT` env var
([#&#8203;971](https://togithub.com/testcontainers/testcontainers-dotnet/issues/971))
[@&#8203;eddumelendez](https://togithub.com/eddumelendez)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/cerbos/cerbos-sdk-net).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi44My4wIiwidXBkYXRlZEluVmVyIjoiMzYuODMuMCIsInRhcmdldEJyYW5jaCI6Im1haW4ifQ==-->

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Oğuzhan Durgun <[email protected]>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants