Bug #8569

DLL exports interfere with Win32 Application Embedding Ruby 1.9.3

Added by George Russell 10 months ago. Updated 10 months ago.

[ruby-core:55654]
Status:Closed
Priority:Normal
Assignee:cruby-windows
Category:-
Target version:-
ruby -v:1.9.3-p429 Backport:1.9.3: UNKNOWN, 2.0.0: UNKNOWN

Description

I am hitting this same situation in embedding Ruby into an existing application: it manifests as crashes in fclose, which on inspection in the debugger, is shown to be the fclose from the Ruby DLL.
It was rather unexpected to have this DLL change the fclose implementation used by the embedding application!

Somewhat frustratingly, while this post proposes a solution, it queries if the solution was correct and desirable, and got no response.

I am using 1.9.3-p429 with MSVC 2008.

Original source: http://www.ruby-forum.com/topic/194276

QUOTE:

Posted by Chris Tenbrink (ctenbrink) on 2009-08-28 23:21
I'm trying to embed ruby 1.9.1 in my Windows application and running
into some problems. I successfully embedded ruby 1.8.4 in the
application, but I'd like to update to use 1.9.1. I'm currently linking
to the .lib and .dll files that I built (using the Microsoft Visual
Studio 2008 compiler) from the ruby 1.9.1 p243 source. I have similar
problems when I link against the 1.9.1 p129 binaries distributed on the
www.ruby-lang.org website.

The root of the problem is that the ruby dll exports a number of
standard library functions that it has redefined. For example, in
include/ruby/win32.h from the source distribution, there are a number of
statements like the following:

#define fclose(f) rbw32fclose(f)

I assume this was done so that when ruby calls fclose() on win32
systems, it would more closely match what happens on other systems when
this function is called. Is this a good assumption?

When I build ruby from source (using the instructions found in
win32/README.win32), code in mkexports.rb causes these redefinitions to
be added to the .def file so that they get exported from the dll. This
causes the redefinitions to be viral - anything that links against the
ruby .lib and uses the ruby .dll uses the redefined functions. I assume
this was done with extension writers in mind so that extension code
automatically uses the same redefined std library functions as ruby
itself. However, for embedding ruby, I'm not sure this makes sense. I
don't mind if ruby does something different with these functions in its
own world, but I don't want the rest of my application to change simply
because I'm now linking in ruby.

I started looking closely at this issue because my application was
crashing when the redefined fclose() was called. It turns out that the
redefined function calls getosfhandle(), and that function doesn't
like the passed in parameter. Thus, the invalid parameter handler gets
called, which, by default, exits the program. One thing that made me
suspicious was that fclose() was redefined for my platform, but fopen()
wasn't.

I got around this issue by commenting out the code in mkexports.rb that
adds these redefinitions to the .def file. This means that the library
functions are still redefined within the ruby dll, but NOT for
applications that link to the .lib. After building ruby and linking it
in with my application, all seems to work out ok. However, I'm reluctant
to implement this as a final solution, because I'd prefer not to ship a
non-standard ruby dll with my application.

In summary, here are my questions:

1) Is it correct to assume that std library functions have been
redefined for win32 ruby to maintain consistency within ruby across
platforms?

2) Are these redefined std library functions exported from the .dll to
ensure extensions use the same code as ruby itself? If so, doesn't this
cause problems for applications that embed ruby?

3) If it's really necessary to redefine fclose(), why isn't fopen()
redefined symmetrically.

4) Am I missing some configuration setting somewhere that will prevent
these redefined functions from being exported from the dll?

5) Is my method of commenting out code to eliminate these exports sound?

Thanks for your help.

Chris Tenbrink

END QUOTE

History

#1 Updated by Luis Lavena 10 months ago

  • Assignee set to cruby-windows

Hello,

The problem with this is that Ruby redefines all those functions in an attempt to ease the cross-platform nature of Ruby C extensions that directly expect some POSIX-like functions behave in the same way.

The ideal scenario will be Ruby core itself uses an abstraction of those functions and leave the platform implementation details to each of the platforms.

But we are talking changing inners part of the code across the entire codebase, which isn't a easy task. Not only that, but the extensions that are depending on those POSIX-isms will require to be updated.

There isn't such interface in CRuby (MRI) that developers can rely on.

Other languages like Node managed to workaround this situation by abstracting the IO layer into libuv library.

If you're looking to embed Ruby-like syntax and not the entire MRI implementation, perhaps you can take a look to mruby:

https://github.com/mruby/mruby

If we get enough attention on this, I would love to contribute.

Cheers.

#2 Updated by George Russell 10 months ago

It would seem sensible a) to warn of this issue in the documentation, so that it does not continue to surprise and b) to suggest a workaround for this issue.

#3 Updated by Luis Lavena 10 months ago

  • Status changed from Open to Closed

Hello,

I'm not a native english speaker, so dunno how to word this accordingly.

Please feel free to take a look to the source code, even on GitHub:

http://github.com/ruby/ruby

Send a pull request and open an issue here for commiters to refer to.

As for the change of behavior, I don't think it will be an easy task, as explained before, so I wouldn't hold my breath until that happens.

Thank you.

Also available in: Atom PDF