• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: RTTI and exceptions between plugins (solution)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: RTTI and exceptions between plugins (solution)


  • Subject: Re: RTTI and exceptions between plugins (solution)
  • From: Steve Baxter <email@hidden>
  • Date: Thu, 1 Nov 2007 17:28:36 +0000

Help!

Last year we had a problem where exceptions and other RTTI used across a DSO boundary would not work properly. We've just discovered that if we compile our project in Xcode 3.0 this stops working again!

We are exporting all symbols from our modules using:

GCC_SYMBOLS_PRIVATE_EXTERN = NO

Has this changed at all in Xcode 3.0 (from 2.4.1)?

Cheers,

Steve

On 3 May 2006, at 13:36, Steve Baxter wrote:

Hi,

I've found a bit of a problem with my solution below.

On 10.4.6, this all works fine - dlopen( RTLD_GLOBAL ) loads my plugins and correctly fixes up all the RTTI information etc. so that the one definition rule is obeyed.

On 10.3.9 however, dlopen( RTLD_GLOBAL ) does not fix up the plugins correctly - modules end up with different RTTI typeid() addresses for the same types (which then causes dynamic_cast to fail).

Does anyone know what could be going on here? I know dlopen() was completely changed for Tiger, but surely the behaviour isn't that broken in Panther?!

Cheers,

Steve.

On 8 Feb 2006, at 0:18, Steve Baxter wrote:

Hi,

Some people (mostly me) have posted here concerning problems with RTTI and exceptions in applications with a plugin architecture. I think I may have found the solution (and possibly a bug in CFBundle, but that kind of depends on your point of view).

Here is the problem:

The GCC C++ runtime support libraries compares type_info objects by address rather than by using their name() value. This behaviour is different to both Codewarrior and VC++. Comparing by pointer is intended to offer better performance, however it introduces a complication with applications that have a plugin architecture.

type_info symbols and other symbols with vague linkage are instantiated as they are compiled:

http://developer.apple.com/documentation/DeveloperTools/gcc-3.3/gcc/Vague-Linkage.html

In a standard application, the linker resolves all these symbols at link time so that the application as a whole has only a single copy of each symbol. With a plugin architecture however there is a problem - it is possible for different plugins to have their own copy of these symbols. The plugins do not link against each other, so the linker does not get a chance to resolve the symbols. When the plugins are loaded, it is possible for the application as a whole to have multiple copies of a symbol. This can lead to RTTI not working properly (an object of class X made by one plugin may not be considered to have type X by another plugin) and exceptions may not work properly, particularly where the exception is a completely inline class.

Note that this situation is technically a bug in the application - it is a violation of the one definition rule:

http://en.wikipedia.org/wiki/One_Definition_Rule

This is a particularly nasty C++ rule as there is no compiler error you will see, your program may just subtly not work properly!

Anyway, the solution to all of this is here:

http://gcc.gnu.org/faq.html#dso

This page says that for this to work:

- Your plugins must export all their symbols

- You must load your plugins using dlopen() with RTLD_GLOBAL

This causes the symbols in each plugin to be added to the application's symbol table as the plugin is loaded. As further plugins are loaded, their symbols will be resolved against the symbols in the already running application, and the one definition rule will be obeyed. If plugin A has symbol X, when plugin B loads that also has symbol X, it will link against plugin A's copy, not its own.

Now for the problem. It is easy to export all the symbols in your plugin - this is the default behaviour in Xcode. If however you load your plugin using CFBundle, it will do the wrong thing. CFBundle loads the plugin (dylib) with private (local) symbols. From CFBundle.c:

NSModule module = NSLinkModule(image, buff, (NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_RETURN_ON_ERROR));

NSLINKMODULE_OPTION_PRIVATE appears to have the same behaviour as RTLD_LOCAL (as far as I can tell, dlopen() actually calls NSLinkModule()). This will prevent symbols being resolved properly across plugins if you use CFBundle. This may be a bug in CFBundle, I'm not sure though (sometimes you might want private visibility for plugins). Possibly the bug is that CFBundle does not give you the choice.

A solution to this is to call dlopen() on the bundle executable with RTLD_GLOBAL before calling CFBundleLoadExecutable(). This forces the dylib to be loaded with global visibility.

OK, hope that helps someone. It's taken me a long time to figure this out for our application! If anyone can think of any simplifications or anything I've missed, I'd be keen to hear them!

Cheers,

Steve.

Steve Baxter
Software Development Manager
Improvision
+44-2476-692229

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden

Steve Baxter Software Development Manager Improvision +44-2476-692229


Steve Baxter Improvision Site Leader PerkinElmer Life and Analytical Sciences email@hidden email@hidden +44-2476-692229

Image Processing and Vision Company Limited (trading as Improvision) is a company registered in England and Wales with company number 2505778. VAT number GB536188722.



_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Prev by Date: Re: Xcode 2.5 can't #include_next <stdarg.h>
  • Next by Date: Re: Xcode 2.5 can't #include_next <stdarg.h>
  • Previous by thread: dyld can't load CoreServices framework
  • Next by thread: Re: XCode 3.0 debugger - almost non-functional
  • Index(es):
    • Date
    • Thread