[Bug 34941] Ruby 1.9.x interpreter hangs with OS-level thread concurrency error (msvcrt internal semi-documented 'ioinfo' structure layout mismatch)

wine-bugs at winehq.org wine-bugs at winehq.org
Tue Dec 10 18:08:47 CST 2013


http://bugs.winehq.org/show_bug.cgi?id=34941

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                URL|http://rubyinstaller.org    |http://dl.bintray.com/onecl
                   |                            |ick/rubyinstaller/rubyinsta
                   |                            |ller-1.9.3-p448.exe
                 CC|                            |focht at gmx.net
          Component|-unknown                    |msvcrt
            Summary|Ruby interpreter hangs with |Ruby 1.9.x interpreter
                   |OS-level thread concurrency |hangs with OS-level thread
                   |error                       |concurrency error (msvcrt
                   |                            |internal semi-documented
                   |                            |'ioinfo' structure layout
                   |                            |mismatch)

--- Comment #2 from Anastasius Focht <focht at gmx.net> 2013-12-10 18:08:47 CST ---
Hello folks,

confirming.

--- snip ---
$  pwd
/home/focht/.wine/drive_c/Ruby193/bin

$ WINEDEBUG=+tid,+seh,+relay wine ./ruby.exe >>log.txt 2>&1
...
0024:Call msvcrt._setmode(00000003,00008000) ret=62d6642b
0024:Ret  msvcrt._setmode() retval=00004000 ret=62d6642b
0024:Call msvcrt._get_osfhandle(00000003) ret=62e6f887
0024:Ret  msvcrt._get_osfhandle() retval=0000005c ret=62e6f887
0024:Call msvcrt._get_osfhandle(00000003) ret=62e6f8ac
0024:Ret  msvcrt._get_osfhandle() retval=0000005c ret=62e6f8ac
0024:Call KERNEL32.PeekConsoleInputA(0000005c,0061f088,00000001,0061f09c)
ret=62e6f8d1
0024:Ret  KERNEL32.PeekConsoleInputA() retval=00000000 ret=62e6f8d1
0024:Call msvcrt.malloc(00002000) ret=62d55130
0024:Call ntdll.RtlAllocateHeap(00110000,00000000,00002000) ret=7ec45a47
0024:Ret  ntdll.RtlAllocateHeap() retval=001fa2d0 ret=7ec45a47
0024:Ret  msvcrt.malloc() retval=001fa2d0 ret=62d55130
0024:trace:seh:__regs_MSVCRT__setjmp buf=0x133918 ebx=00133850 esi=001338bc
edi=00000000 ebp=0061f018 esp=0061effc eip=62e5f8da frame=0061fed8
0024:Call KERNEL32.ReleaseMutex(00000050) ret=62e631d3
0024:Ret  KERNEL32.ReleaseMutex() retval=00000001 ret=62e631d3
0024:Call msvcrt._get_osfhandle(00000003) ret=62e76c91
0024:Ret  msvcrt._get_osfhandle() retval=0000005c ret=62e76c91
0024:Call msvcrt._get_osfhandle(00000003) ret=62e76cb6
0024:Ret  msvcrt._get_osfhandle() retval=0000005c ret=62e76cb6
0025:Ret  KERNEL32.WaitForSingleObject() retval=00000102 ret=62e5d039
0025:Call KERNEL32.WaitForSingleObject(00000054,00000064) ret=62e5d039
0025:Ret  KERNEL32.WaitForSingleObject() retval=00000102 ret=62e5d039 
...
0025:Call KERNEL32.WaitForSingleObject(00000054,00000064) ret=62e5d039
0024:err:ntdll:RtlpWaitForCriticalSection section 0x122108 "?" wait timed out
in thread 0024, blocked by 0000, retrying (60 sec)
0025:Ret  KERNEL32.WaitForSingleObject() retval=00000102 ret=62e5d039 
--- snip ---

Tid 0025 seems harmless. Looks like a fast running ruby 'timer' thread which
peeks every 100ms for some work and executes 'tasklets' if needed.

Tid 0024 is the culprit here. Using the version info along with some
debugging/disassembly I found the code which most likely resembles the
problem/trace log -> rb_w32_read():

Source:
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_9_3/win32/win32.c?revision=37549&view=markup&pathrev=37743

(binary 'msvcrt-ruby191.dll')

--- snip ---
5183     #undef read
5184     ssize_t
5185     rb_w32_read(int fd, void *buf, size_t size)
5186     {
5187     SOCKET sock = TO_SOCKET(fd);
5188     DWORD read;
5189     DWORD wait;
5190     DWORD err;
5191     size_t len;
5192     size_t ret;
5193     OVERLAPPED ol, *pol = NULL;
5194     BOOL isconsole;
5195     BOOL islineinput = FALSE;
5196     int start = 0;
5197     
5198     if (is_socket(sock))
5199     return rb_w32_recv(fd, buf, size, 0);
5200     
5201     // validate fd by using _get_osfhandle() because we cannot access
_nhandle
5202     if (_get_osfhandle(fd) == -1) {
5203     return -1;
5204     }
5205     
5206     if (_osfile(fd) & FTEXT) {
5207     return _read(fd, buf, size);
5208     }
5209     
5210     MTHREAD_ONLY(EnterCriticalSection(&(_pioinfo(fd)->lock)));
5211     
...
--- snip ---

Line 5210 seems to be the matching source line to EnterCriticalSection ->
RtlpWaitForCriticalSection (see timeout message with the invalid blocking tid)

The problem seems to be that Ruby's win32 wrapper makes direct use of msvcrt
internal data structures, making assumptions about the layout.

--- snip ---
...
2021     typedef struct {
2022         intptr_t osfhnd; /* underlying OS file HANDLE */
2023         char osfile; /* attributes of file (e.g., open in text mode?) */
2024         char pipech; /* one char buffer for handles opened on pipes */
2025     #ifdef MSVCRT_THREADS
2026         int lockinitflag;
2027         CRITICAL_SECTION lock;
2028     #endif
2029     #if RT_VER >= 80
2030         char textmode;
2031         char pipech2[2];
2032     #endif
2033     } ioinfo;
2034     
2035     #if !defined _CRTIMP || defined __MINGW32__
2036     #undef _CRTIMP
2037     #define _CRTIMP __declspec(dllimport)
2038     #endif
2039     
2040     #if !defined(__BORLANDC__)
2041     EXTERN_C _CRTIMP ioinfo * __pioinfo[];
2042     
2043     #define IOINFO_L2E 5
2044     #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
2045     #define _pioinfo(i) ((ioinfo*)((char*)(__pioinfo[i >> IOINFO_L2E]) +
(i & (IOINFO_ARRAY_ELTS - 1)) * (sizeof(ioinfo) + pioinfo_extra)))
2046     #define _osfhnd(i) (_pioinfo(i)->osfhnd)
2047     #define _osfile(i) (_pioinfo(i)->osfile)
2048     #define _pipech(i) (_pioinfo(i)->pipech)
2049     
2050     #if RT_VER >= 80
2051     static size_t pioinfo_extra = 0; /* workaround for VC++8 SP1 */
...
--- snip ---

If we compare it to Wine's ioinfo, which is exported through __pioinfo
(internally MSVCRT___pioinfo) array:

Source:
http://source.winehq.org/git/wine.git/blob/3bb2c11757156223be0f8a22f3b377b060b09562:/dlls/msvcrt/file.c#l84

--- snip ---
84 /* ioinfo structure size is different in msvcrXX.dll's */
85 typedef struct {
86     HANDLE handle;
87     unsigned char wxflag;
88     char lookahead[3];
89     int exflag;
90     CRITICAL_SECTION crit;
91 } ioinfo;
--- snip ---

This obviously can't work.

Maybe Wine's ioinfo structure layout could be made more compatible with Ruby's
ioinfo definition, matching MS CRT.

There are various other open source projects which directly access this
'semi-documented' internal structure (python, stlport, cygwin, msys ...).
Making Wine more compatible would help other python, cygwin, msys related bugs.

$ sha1sum rubyinstaller-1.9.3-p448.exe 
728dae18b46611a28b2ae542e68eb0d22c66a087  rubyinstaller-1.9.3-p448.exe

$ du -sh rubyinstaller-1.9.3-p448.exe 
15M    rubyinstaller-1.9.3-p448.exe

$ wine --version
wine-1.7.8-135-gfaa355b

Regards

-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
Do not reply to this email, post in Bugzilla using the
above URL to reply.
------- You are receiving this mail because: -------
You are watching all bug changes.



More information about the wine-bugs mailing list