Bug #18605


Fails to run on (newer) 32bit Windows with ucrt

Added by lazka (Christoph Reiter) about 2 years ago. Updated 11 months ago.

Target version:


32bit ruby using ucrt has started to fail on newer Windows with "unexpected ucrtbase.dll" ->

The problem is that ruby depends on ucrt internals and those have apparently changed with newer versions.

See and for some background and a potential fix. But ideally ruby wouldn't depend on Windows internals like this.


Related issues 1 (0 open1 closed)

Related to Ruby master - Bug #11118: Unable to build Ruby with Visual Studio 2015 RCClosedActions
Actions #1

Updated by naruse (Yui NARUSE) about 2 years ago

  • Related to Bug #11118: Unable to build Ruby with Visual Studio 2015 RC added

Updated by naruse (Yui NARUSE) about 2 years ago

Why Ruby depends to _pioinfo is

  • to associate socket and fd: CRuby creates fd with dummy file handle and set socket to emulate Unix-like behavior
  • to implement overlapped I/O for Windows 2000/XP
  • to emulate fcntl(2)

If you know a better way to implement above use cases, we will migrate to that.


Updated by ivall (ivall ivall) over 1 year ago

I have same problem on Windows 11 25206, reinstalling Ruby didn't help.

Updated by MSP-Greg (Greg L) over 1 year ago

An issue exists elsewhere, see I'm just the messenger, I don't have the knowledge needed for this issue.

Quoting the response from ArminG-MSFT:

Hello this is Armin from Microsoft. We encountered the same or at least a very similar issue in our internal compatibility testing. What seems to be the issue is that Ruby is relying on undocumented/unsupported behaviour. It is trying to retrieve a pointer to an internal variable __pioinfo inside urtbase.dll. That itself is not supported, but from our debugging and looking at the code in win32.c it looks like it is doing it by walking back from the ret assembly instruction in _isatty(). But this assumes the ret instruction will be the last instruction in that _isatty().

The issue is that certain optimizations can move function code beyond a ret instruction, so the common/typical instruction path is shorter. And new optimizations we applied to recent ucrtbase.dll builds did exactly that in _isatty(). So it looks like Ruby is now looking at the wrong location and no longer finding __pioinfo.

Short term we'll be rolling out a fix that for this function that undoes this optimization, which should fix this specific error for the many Ruby users in the wild. But it would be great if Ruby can be fixed to not use undocumented behaviour, or perhaps at least be more robust in its function traversal. Note though that at some point we may break it in some way that is not so easily fixed.

The offending code is in win32\win32.c function set_pioinfo_extra.

Feel free to correct me though if our understanding is incorrect.

Updated by lazka (Christoph Reiter) over 1 year ago

This (unsurprisingly) also breaks ruby on arm64 and is blocking our arm64 porting effort:

Updated by larskanis (Lars Kanis) over 1 year ago

Thanks all for sharing the details!

I started a branch to replace the UCRT/MSVCRT pioinfo here:

My rough plan is to first replace pioinfo with a ruby-internal mapping between FD and HANDLE/SOCKET. This makes it necessary to replace all uses of FD and change it to native WINAPI functions using HANDLE/SOCKET. Fortunately many functions are already based on the native WINAPI. Among others it currently fails at the many process spawn variations and the text file CRLF conversions are not yet implemented. Also the few uses of FILE based libc functions still have to be replaced.

After pioinfo is replaced and the implementation is passing all tests again, I would like to replace FD completely by HANDLE/SOCKET including in IO#fileno and This is because the FD is then just an internal number, with no external meaning. But HANDLE/SOCKET is the native Windows handle to access resources and to process events.

Even if this sounds pretty simple, there are a lot of tricky challenges on the way and I'm sure @naruse (Yui NARUSE) had very good reasons to build the pioinfo hack.

Updated by awhitenose (Alex Whitenose) 11 months ago

I have created a simple fix which helped to run 32-bit Ruby 2.6.x up to 3.2.x on Windows 11 without getting 'unexpected ucrtbase.dll' anymore.

Available here:

64-bit is unaffected. But it obviously does not make any changes or help for ARM builds.


Also available in: Atom PDF