Jump to page: 1 2
Thread overview
[D-runtime] Runtime issue on Mac OS X
Jun 02, 2012
Jacob Carlborg
Jun 20, 2012
Sean Kelly
Jun 20, 2012
Jacob Carlborg
Jun 21, 2012
Sean Kelly
Jun 21, 2012
Brad Roberts
Jun 21, 2012
Sean Kelly
Jun 21, 2012
Jacob Carlborg
Jun 21, 2012
Brad Roberts
Jun 22, 2012
Sean Kelly
Jun 22, 2012
Jacob Carlborg
Jun 23, 2012
Martin Nowak
Jun 21, 2012
Jacob Carlborg
June 02, 2012
When I was trying to fix issue 7995 I created the pull request:

https://github.com/D-Programming-Language/druntime/pull/228

In that pull request it has come to my attention that following system functions doesn't play nice with dynamic libraries:

_dyld_register_func_for_add_image _dyld_register_func_for_remove_image

http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/MachOReference/Reference/reference.html

This two functions are used in memory_osx.d to install callbacks for getting various data out of the loaded images, like TLS data, module infos, exception handling tables and so on. These callbacks are called, among other cases, when dlopen/dlclose is called.

In the discussion in the pull request dawgfoto (Martin Nowak) pointed out that it's not very good to use any of the above two functions in a dynamic library loaded via "dlopen".

The problem is that the callbacks are never removed from the internal list of callbacks. So if a dynamic library uses these functions and then gets unloaded. Next time dlopen/dlclose is called the application will crash because it tries to call the callback from the now unloaded library.

There doesn't seem to be a way to unregister these callbacks.

This example shows the problem

http://pastebin.com/yUKBgu8Y

When running "main" from the above a Bus error will occur.

I did some digging and found a solutions that seems to work:

http://pastebin.com/qZfiWRbN

The only difference compared to the implementation we have now is that the callback called when unloading a dylib is not called for the dylib that installed it. In the example above that would mean that "onUnload" is not called when foo.dylibis unloaded. Note that the callback is still called when bar.dylibis unloaded.

The problem with the implementation above is that "dyld_register_image_state_change_handler" is a private undocumented function in libdyld.dylib. This function has been available since Mac OS X 10.5 and is used by the Objective-C runtime.

All of this is only an issue if the D runtime is dynamically loaded, which isn't supported yet.

-- 
/Jacob Carlborg

_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

June 20, 2012
A lot of work needs to be done to support dynamic libraries properly.  Thread lists need to be dynamically merged and unmerged, static segment info, ModuleInfo, etc.  We already have Runtime.load/unloadLibrary, so if we assume that D programmers will always call these instead of dlopen/dlclose directly then we just need to make sure the routines handle both C and D dynamic libraries appropriately.  Also, it should be possible to use the same D dynamic library with both C and D apps, which I guess means that Druntime would have to live in its own dynamic library as well.

On Jun 2, 2012, at 10:15 AM, Jacob Carlborg wrote:

> When I was trying to fix issue 7995 I created the pull request:
> 
> https://github.com/D-Programming-Language/druntime/pull/228
> 
> In that pull request it has come to my attention that following system functions doesn't play nice with dynamic libraries:
> 
> _dyld_register_func_for_add_image _dyld_register_func_for_remove_image
> 
> http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/MachOReference/Reference/reference.html
> 
> This two functions are used in memory_osx.d to install callbacks for getting various data out of the loaded images, like TLS data, module infos, exception handling tables and so on. These callbacks are called, among other cases, when dlopen/dlclose is called.
> 
> In the discussion in the pull request dawgfoto (Martin Nowak) pointed out that it's not very good to use any of the above two functions in a dynamic library loaded via "dlopen".
> 
> The problem is that the callbacks are never removed from the internal list of callbacks. So if a dynamic library uses these functions and then gets unloaded. Next time dlopen/dlclose is called the application will crash because it tries to call the callback from the now unloaded library.
> 
> There doesn't seem to be a way to unregister these callbacks.
> 
> This example shows the problem
> 
> http://pastebin.com/yUKBgu8Y
> 
> When running "main" from the above a Bus error will occur.
> 
> I did some digging and found a solutions that seems to work:
> 
> http://pastebin.com/qZfiWRbN
> 
> The only difference compared to the implementation we have now is that the callback called when unloading a dylib is not called for the dylib that installed it. In the example above that would mean that "onUnload" is not called when foo.dylibis unloaded. Note that the callback is still called when bar.dylibis unloaded.
> 
> The problem with the implementation above is that "dyld_register_image_state_change_handler" is a private undocumented function in libdyld.dylib. This function has been available since Mac OS X 10.5 and is used by the Objective-C runtime.
> 
> All of this is only an issue if the D runtime is dynamically loaded, which isn't supported yet.
> 
> -- 
> /Jacob Carlborg
> 
> _______________________________________________
> D-runtime mailing list
> D-runtime@puremagic.com
> http://lists.puremagic.com/mailman/listinfo/d-runtime

_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

June 20, 2012
On 20 jun 2012, at 19:28, Sean Kelly wrote:

> A lot of work needs to be done to support dynamic libraries properly.  Thread lists need to be dynamically merged and unmerged, static segment info, ModuleInfo, etc.  We already have Runtime.load/unloadLibrary, so if we assume that D programmers will always call these instead of dlopen/dlclose directly then we just need to make sure the routines handle both C and D dynamic libraries appropriately.  Also, it should be possible to use the same D dynamic library with both C and D apps, which I guess means that Druntime would have to live in its own dynamic library as well.


Yeah, I know. I know in theory what's need to be done (and I'm probably missing somethings here as well). But it's these particle things that cause problems, like _dyld_register_func_for_add_image probably can't be used.

Are you suggesting _dyld_register_func_for_add_image should not be used and to all initialization in Runtime.load?

_dyld_register_func_for_add_image is used to get the mach_header of a loaded image (dynamic library or executable) which is needed to get module info, TSL data and so on. How should that be obtained otherwise:

* Iterating all loaded images - Sure, it works, I've done that, but it not as pretty

* Bracketing sections with empty sections, i.e. _tls_beg, _tls_end - I would rather not go back to this solution. It was recently removed in favor of getsectbynamefromheader (which requires a  mach_header) because it's much more reliable. We won't have problems with newer version of the linker

* Using "dladdr" somehow to get the mach_header

* Other suggestions I'm not aware of / have missed

If we can use "dyld_register_image_state_change_handler" that would be nice. But as I've said, it's a private function. Also I don't think it's possible to unload a dynamic library which uses this function. Although the Objective-C runtime uses it so I don't know if it's a problem or not.

-- 
/Jacob Carlborg

_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

June 20, 2012
On Jun 20, 2012, at 1:53 PM, Jacob Carlborg wrote:

> 
> On 20 jun 2012, at 19:28, Sean Kelly wrote:
> 
>> A lot of work needs to be done to support dynamic libraries properly.  Thread lists need to be dynamically merged and unmerged, static segment info, ModuleInfo, etc.  We already have Runtime.load/unloadLibrary, so if we assume that D programmers will always call these instead of dlopen/dlclose directly then we just need to make sure the routines handle both C and D dynamic libraries appropriately.  Also, it should be possible to use the same D dynamic library with both C and D apps, which I guess means that Druntime would have to live in its own dynamic library as well.
> 
> 
> Yeah, I know. I know in theory what's need to be done (and I'm probably missing somethings here as well). But it's these particle things that cause problems, like _dyld_register_func_for_add_image probably can't be used.

It can't be used if a dynamic library calls this function and is then later unloaded via dlclose.  The easy way out would be to say that the result of calling dlclose on a Druntime dynamic library is undefined, and then put Druntime in its own dynamic library so random D dynamic libraries could be loaded and unloaded safely.  If you call dlopen for a library once, future dlopen calls will be effectively no-ops, right?

One not great alternative would be to provide a function that registers a trampoline function in the calling process.  I'd guess this would mean passing in the address of a static void* to hold this to rt_init() or something though.

It's weird that there's no unregister function.  Have you checked the darwin sources?

_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

June 20, 2012
The better fix is to register just one hook via the main app startup and have subsequently opened libraries hook in via a druntime api that maintains a list that can be removed from safely.

On Wed, 20 Jun 2012, Sean Kelly wrote:

> Date: Wed, 20 Jun 2012 17:02:18 -0700
> From: Sean Kelly <sean@invisibleduck.org>
> Reply-To: D's runtime library developers list <d-runtime@puremagic.com>
> To: D's runtime library developers list <d-runtime@puremagic.com>
> Subject: Re: [D-runtime] Runtime issue on Mac OS X
> 
> On Jun 20, 2012, at 1:53 PM, Jacob Carlborg wrote:
> 
> > 
> > On 20 jun 2012, at 19:28, Sean Kelly wrote:
> > 
> >> A lot of work needs to be done to support dynamic libraries properly.  Thread lists need to be dynamically merged and unmerged, static segment info, ModuleInfo, etc.  We already have Runtime.load/unloadLibrary, so if we assume that D programmers will always call these instead of dlopen/dlclose directly then we just need to make sure the routines handle both C and D dynamic libraries appropriately.  Also, it should be possible to use the same D dynamic library with both C and D apps, which I guess means that Druntime would have to live in its own dynamic library as well.
> > 
> > 
> > Yeah, I know. I know in theory what's need to be done (and I'm probably missing somethings here as well). But it's these particle things that cause problems, like _dyld_register_func_for_add_image probably can't be used.
> 
> It can't be used if a dynamic library calls this function and is then later unloaded via dlclose.  The easy way out would be to say that the result of calling dlclose on a Druntime dynamic library is undefined, and then put Druntime in its own dynamic library so random D dynamic libraries could be loaded and unloaded safely.  If you call dlopen for a library once, future dlopen calls will be effectively no-ops, right?
> 
> One not great alternative would be to provide a function that registers a trampoline function in the calling process.  I'd guess this would mean passing in the address of a static void* to hold this to rt_init() or something though.
> 
> It's weird that there's no unregister function.  Have you checked the darwin sources?
> 
> _______________________________________________
> D-runtime mailing list
> D-runtime@puremagic.com
> http://lists.puremagic.com/mailman/listinfo/d-runtime
> 
_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

June 20, 2012
This is great if the main app is D but harder (or at least more visible) if it's C.

On Jun 20, 2012, at 9:47 PM, Brad Roberts <braddr@puremagic.com> wrote:

> The better fix is to register just one hook via the main app startup and have subsequently opened libraries hook in via a druntime api that maintains a list that can be removed from safely.
> 
> On Wed, 20 Jun 2012, Sean Kelly wrote:
> 
>> Date: Wed, 20 Jun 2012 17:02:18 -0700
>> From: Sean Kelly <sean@invisibleduck.org>
>> Reply-To: D's runtime library developers list <d-runtime@puremagic.com>
>> To: D's runtime library developers list <d-runtime@puremagic.com>
>> Subject: Re: [D-runtime] Runtime issue on Mac OS X
>> 
>> On Jun 20, 2012, at 1:53 PM, Jacob Carlborg wrote:
>> 
>>> 
>>> On 20 jun 2012, at 19:28, Sean Kelly wrote:
>>> 
>>>> A lot of work needs to be done to support dynamic libraries properly.  Thread lists need to be dynamically merged and unmerged, static segment info, ModuleInfo, etc.  We already have Runtime.load/unloadLibrary, so if we assume that D programmers will always call these instead of dlopen/dlclose directly then we just need to make sure the routines handle both C and D dynamic libraries appropriately.  Also, it should be possible to use the same D dynamic library with both C and D apps, which I guess means that Druntime would have to live in its own dynamic library as well.
>>> 
>>> 
>>> Yeah, I know. I know in theory what's need to be done (and I'm probably missing somethings here as well). But it's these particle things that cause problems, like _dyld_register_func_for_add_image probably can't be used.
>> 
>> It can't be used if a dynamic library calls this function and is then later unloaded via dlclose.  The easy way out would be to say that the result of calling dlclose on a Druntime dynamic library is undefined, and then put Druntime in its own dynamic library so random D dynamic libraries could be loaded and unloaded safely.  If you call dlopen for a library once, future dlopen calls will be effectively no-ops, right?
>> 
>> One not great alternative would be to provide a function that registers a trampoline function in the calling process.  I'd guess this would mean passing in the address of a static void* to hold this to rt_init() or something though.
>> 
>> It's weird that there's no unregister function.  Have you checked the darwin sources?
>> 
>> _______________________________________________
>> D-runtime mailing list
>> D-runtime@puremagic.com
>> http://lists.puremagic.com/mailman/listinfo/d-runtime
>> 
> _______________________________________________
> D-runtime mailing list
> D-runtime@puremagic.com
> http://lists.puremagic.com/mailman/listinfo/d-runtime
_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

June 21, 2012
On 21 jun 2012, at 02:02, Sean Kelly wrote:
> It can't be used if a dynamic library calls this function and is then later unloaded via dlclose.  The easy way out would be to say that the result of calling dlclose on a Druntime dynamic library is undefined, and then put Druntime in its own dynamic library so random D dynamic libraries could be loaded and unloaded safely.

Yeah, that would be one idea. But what about dyld_register_image_state_change_handler?

> If you call dlopen for a library once, future dlopen calls will be effectively no-ops, right?

Yes, it will increment a counter.  One needs to match all dlopen with a dlclose to be safe.

> One not great alternative would be to provide a function that registers a trampoline function in the calling process.  I'd guess this would mean passing in the address of a static void* to hold this to rt_init() or something though.
> 
> It's weird that there's no unregister function.  Have you checked the darwin sources?

Yes, I've checked the source code for dyld (the dynamic loader). Again, what about dyld_register_image_state_change_handle? Using that function will work as proven by this example:

http://pastebin.com/qZfiWRbN

-- 
/Jacob Carlborg

_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

June 21, 2012
On 21 jun 2012, at 07:16, Sean Kelly wrote:

> This is great if the main app is D but harder (or at least more visible) if it's C.


It feels like we can almost make initializing of the D runtime and loading of dynamic libraries work transparently. But it's just out of reach.

-- 
/Jacob Carlborg

_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

June 21, 2012
C apps still must initialize the d runtime, so do it from rt_init() or whatever the function is called these days.

On Wed, 20 Jun 2012, Sean Kelly wrote:

> Date: Wed, 20 Jun 2012 22:16:48 -0700
> From: Sean Kelly <sean@invisibleduck.org>
> Reply-To: D's runtime library developers list <d-runtime@puremagic.com>
> To: D's runtime library developers list <d-runtime@puremagic.com>
> Subject: Re: [D-runtime] Runtime issue on Mac OS X
> 
> This is great if the main app is D but harder (or at least more visible) if it's C.
> 
> On Jun 20, 2012, at 9:47 PM, Brad Roberts <braddr@puremagic.com> wrote:
> 
> > The better fix is to register just one hook via the main app startup and have subsequently opened libraries hook in via a druntime api that maintains a list that can be removed from safely.
> > 
> > On Wed, 20 Jun 2012, Sean Kelly wrote:
> > 
> >> Date: Wed, 20 Jun 2012 17:02:18 -0700
> >> From: Sean Kelly <sean@invisibleduck.org>
> >> Reply-To: D's runtime library developers list <d-runtime@puremagic.com>
> >> To: D's runtime library developers list <d-runtime@puremagic.com>
> >> Subject: Re: [D-runtime] Runtime issue on Mac OS X
> >> 
> >> On Jun 20, 2012, at 1:53 PM, Jacob Carlborg wrote:
> >> 
> >>> 
> >>> On 20 jun 2012, at 19:28, Sean Kelly wrote:
> >>> 
> >>>> A lot of work needs to be done to support dynamic libraries properly.  Thread lists need to be dynamically merged and unmerged, static segment info, ModuleInfo, etc.  We already have Runtime.load/unloadLibrary, so if we assume that D programmers will always call these instead of dlopen/dlclose directly then we just need to make sure the routines handle both C and D dynamic libraries appropriately.  Also, it should be possible to use the same D dynamic library with both C and D apps, which I guess means that Druntime would have to live in its own dynamic library as well.
> >>> 
> >>> 
> >>> Yeah, I know. I know in theory what's need to be done (and I'm probably missing somethings here as well). But it's these particle things that cause problems, like _dyld_register_func_for_add_image probably can't be used.
> >> 
> >> It can't be used if a dynamic library calls this function and is then later unloaded via dlclose.  The easy way out would be to say that the result of calling dlclose on a Druntime dynamic library is undefined, and then put Druntime in its own dynamic library so random D dynamic libraries could be loaded and unloaded safely.  If you call dlopen for a library once, future dlopen calls will be effectively no-ops, right?
> >> 
> >> One not great alternative would be to provide a function that registers a trampoline function in the calling process.  I'd guess this would mean passing in the address of a static void* to hold this to rt_init() or something though.
> >> 
> >> It's weird that there's no unregister function.  Have you checked the darwin sources?
> >> 
> >> _______________________________________________
> >> D-runtime mailing list
> >> D-runtime@puremagic.com
> >> http://lists.puremagic.com/mailman/listinfo/d-runtime
> >> 
> > _______________________________________________
> > D-runtime mailing list
> > D-runtime@puremagic.com
> > http://lists.puremagic.com/mailman/listinfo/d-runtime
> _______________________________________________
> D-runtime mailing list
> D-runtime@puremagic.com
> http://lists.puremagic.com/mailman/listinfo/d-runtime
> 
_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

June 21, 2012
On Jun 21, 2012, at 11:23 AM, Brad Roberts wrote:

> C apps still must initialize the d runtime, so do it from rt_init() or whatever the function is called these days.

Or the library could expose an init() call of its own that first calls rt_init().  Either way, I think this is different from requiring the app developer to provide a static address or whatever for the function map.
_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

« First   ‹ Prev
1 2