Closed Bug 186599 Opened 22 years ago Closed 22 years ago

PR_LoadLibrary() doesn't support relative paths.

Categories

(NSPR :: NSPR, defect)

PowerPC
macOS
defect
Not set
normal

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: dougt, Assigned: ccarlen)

References

Details

Attachments

(2 files, 3 obsolete files)

I ask ccarlen to look at the failure of xpcom glue on OSX. Apparently, the nspr's PR_LoadLibrary function doesn't handle relative paths correctly. ConradCarlen: heh - all this should take to fix is one call to realpath(3)
Could you give me a test case or point out where the error is in the source code? Thanks.
xpcom/sample/nsTestSample, this fails on OSX but works on Linux, presumeably win32.
Blocks: 173262
Blocks: gre
> or point out where the error is in the source code? http://lxr.mozilla.org/seamonkey/source/nsprpub/pr/src/linking/prlink.c#763 Apparently, FSPathMakeRef() requires a full path. If the "name" param is made to be a full path by realpath(3), it works. There's more to this problem. We end up trying to use NSCreateObjectFileImageFromFile to load the lib. That won't work on a lib linked without the -bundle flag, as libxpcom.dylib is :-/
Doug, You will need to build a version of the xpcom library with the -bundle flag. Only that version (which would most likely be called libxpcom.bundle) can be dynamically loaded. On Mac OS X a dynamic shared library (.dylib) and a loadable bundle (.bundle) are different things while on Unix and Windows .so and .dll can be used in both ways.
do we really need two versions? (Why would i ever want a shared library that can't be programmatically loaded?)
Doug, this is one peculiarity of Mac OS X (or rather Darwin). libxpcom.dylib is a shared library that you can specify at link time with the -lxpcom flag. Obviously shared libraries used in this way are still useful. libxpcom.bundle is a shared library that you can load at run time with the equivalent of the dlopen() function. I asked your first question on macdev@netscape.com before and the answer I got was yes, we really need two versions.
I wonder what the reasons were.... also, maybe the way I am attempting the support of the GRE is incorrect on OSX. do we need to do this same dual library trick for other libraries while we are touching stuff?
Comment on attachment 110043 [details] [diff] [review] Create libxpcom.bundle patch looks good to me, r=mcafee
Attachment #110043 - Flags: review+
chris, can you/i check this patch in?
(I updated my other patches to look for a libxpcom.bundle instead of libxpcom.so on macosx)
The patch has been checked in.
Doug - is the original problem reported, which the patch doesn't address, still an issue? The header doc for PR_LoadLibrary doesn't specify that the given path can be relative or full. Not supporting relative paths was a problem for a test app. Since we obviously use full paths everywhere else, should this just be fixed in the test app?
i do not know how loading libraries (or bundles) on OS X works. However, I want to be able to do something like this: PR_LoadLibary("./foo.bundle"); Is that supported?
PR_LoadLibrary should support relative paths.
So this is fixed then ?
no. it is still broken. conrad is going to look at it shortly.
Attached patch patch allow relative paths, etc. (obsolete) — Splinter Review
diff lost its mind on this one - the changes aren't as strange as they look. Basically, this breaks the different methods that can be used to load libs on the mac into subroutines, and calls those in a certain order depending on what type of runtime arch we are - the format that is most native is tried first. This fixes the performance loss reported in bug 187185. Relative paths now work. For Mach-O, this is because the new code goes straight to NSCreateObjectFileImageFromFile(), which can work with a relative path. Before, it used to fail on relative paths because of some Mac file mgr calls which that were done for the benefit of CFM library loading calls.
Attachment #110843 - Flags: superreview?(sfraser)
Attachment #110843 - Flags: review?(wtc)
Could you attach the entire file, for ease of viewing? Thanks.
Attached file complete prlink.c (obsolete) —
Here is the complete file. If you apply the patch to a copy, CodeWarrior gives a much clearer diff.
Comments: > /* > * macLibraryLoadProc is a function definition for a Mac shared library > * loading method. The "name" param is the same full or partial pathname > * that was passed to pr_LoadLibraryByPathName. The function must fill > * in the fields of "lm" which apply to its library type as well as the > * "name" field. Returns 0 if successful. > */ > > typedef PRInt32 (*macLibraryLoadProc)(const char *name, PRLibrary *lm); I think this should return an OSErr, or, if it's too hard to unify different error spaces, just a boolean. > /* > ** Returns a CFBundleRef if the file name refers to a Mac OS X bundle directory. > ** The caller is responsible for calling CFRelease() to deallocate. > */ Comments looks incorrect. This returns errors, not CFBundleRefs. > #if TARGET_CARBON > static PRInt32 loadBundle(const char *name, PRLibrary *lm) > { > CFURLRef bundleURL; > CFBundleRef bundle = NULL; > > #ifdef XP_MACOSX > char pathBuf[PATH_MAX]; > const char *resolvedPath; > CFStringRef pathRef; > > /* Takes care of relative paths and symlinks */ > resolvedPath = realpath(name, pathBuf); > if (!resolvedPath) > return errno; If you decide to return OSErrs, need to convert errno to an OSErr. > #if defined(XP_MAC) || defined(XP_MACOSX) > { > int i; > OSErr err; > > macLibraryLoadProc loadProcs[] = { > #if defined(XP_MACOSX) > loadViaDyld, loadBundle, loadViaCFM > #elif TARGET_CARBON > loadViaCFM, loadBundle > #else > loadViaCFM > #endif > }; Make loadProcs const and static? > #elif defined(USE_MACH_DYLD) > NSObjectFileImage ofi; > NSModule h = NULL; > if (NSCreateObjectFileImageFromFile(name, &ofi) > == NSObjectFileImageSuccess) { > h = NSLinkModule(ofi, name, NSLINKMODULE_OPTION_PRIVATE); > } Do we need this stuff any more? It's confusing to have this code appear twice. > #ifdef XP_UNIX > #ifdef HAVE_DLL > #ifdef USE_DLFCN > result = dlclose(lib->dlh); > #elif defined(USE_HPSHL) > result = shl_unload(lib->dlh); > #elif defined(USE_MACH_DYLD) > result = NSUnLinkModule(lib->dlh, FALSE); > #else > #error Configuration error > #endif > #endif /* HAVE_DLL */ > #endif /* XP_UNIX */ > #ifdef XP_PC > if (lib->dlh) { > FreeLibrary((HINSTANCE)(lib->dlh)); > lib->dlh = (HINSTANCE)NULL; > } > #endif /* XP_PC */ > > #if defined(XP_MAC) || defined(XP_MACOSX) > /* Close the connection */ > if (lib->connection) > CloseConnection(&(lib->connection)); > #if TARGET_CARBON > if (lib->bundle) > CFRelease(lib->bundle); > #endif > #if defined(XP_MACOSX) > if (lib->wrappers) > CFRelease(lib->wrappers); > #endif > #endif > It's unfortunate that the unloading code doesn't use the same #ifdef layout as the loading code. Uloading Mac OS X dylibs falls under #ifdef UNIX && defined(USE_MACH_DYLD), which is rather confusing. I think this should be fixed.
Simon - I agree and will post a new patch. typedef PRInt32 (*macLibraryLoadProc)(const char *name, PRLibrary *lm); I'll make it return PRBool because of the various error code spaces. USE_MACH_DYLD, outside of XP_MACOSX, does lead to some ugliness :-/ This still exists separately for the sake of the NextStep build of NSPR. If that isn't a supported build, things defined for USE_MACH_DYLD could be pulled inside XP_MACOSX. I assumed that we wanted the NextStep build to still work. Anybody know its status?
Status: NEW → ASSIGNED
USE_MACH_DYLD (i.e., standalone Darwin) should continue to work.
Attached patch patch v2 (obsolete) — Splinter Review
Changed the return type of (*macLibraryLoadProc)() to PRBool for success/failure. Made macLibraryLoadProc loadProcs[] = ... static const Replaced some #ifdef DEBUG printfs in Mac code with PR_LOG Most of the XP_MACOSX work in this file is done with USE_MACH_DYLD. There are now two occurances of NSCreateObjectFileImageFromFile(), but I can't see a way of fixing that. Anyway, it's better than the existing goto which allows us to fall through to some USE_MACH_DYLD code below. I think the only way this could really be cleaned up is to break it all out into md code.
Attachment #110843 - Attachment is obsolete: true
Attachment #110872 - Attachment is obsolete: true
Comment on attachment 110843 [details] [diff] [review] patch allow relative paths, etc. I wish when you obsoleted a patch, requests were canceled automatically.
Attachment #110843 - Flags: superreview?(sfraser)
Attachment #110843 - Flags: review?(wtc)
Attachment #111019 - Flags: superreview?(sfraser)
Attachment #111019 - Flags: review?(wtc)
Attachment #111019 - Flags: superreview?(sfraser) → superreview+
Comment on attachment 111019 [details] [diff] [review] patch v2 This patch assumes that TARGET_RT_MAC_CFM is 1 if XP_MAC is defined. Is that a valid assumption?
Yes, looking at <TargetConditionals.h>, and given how we define XP_MAC and XP_MACOSX.
Attached patch patch v3Splinter Review
Your patch is very good, Conrad. Thank you. I just did some editing to follow the NSPR coding style. 1. I added the pr_ prefix to the new static functions. 2. I did some formatting of the comment blocks and broke long lines into lines shorter than 80 columns. 3. I changed the macLibraryLoadProc function to return PRStatus instead of PRBool and not to set lm->name. lm->name is now set by pr_LoadLibraryByPathName. 4. I added a new static function for the common code (NSCreateObjectFileImageFromFile) between XP_MACOSX and USE_MACH_DYLD.
Attachment #111019 - Attachment is obsolete: true
I've checked in the patch on the NSPR trunk and NSPRPUB_PRE_4_2_CLIENT_BRANCH. Doug, could you verify that PR_LoadLibrary now supports relative paths?
Status: ASSIGNED → RESOLVED
Closed: 22 years ago
OS: Windows XP → MacOS X
Resolution: --- → FIXED
Target Milestone: --- → 4.3
Attachment #111019 - Flags: review?(wtc)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: