change `ffi-lib' to not make library symbols global by default

This commit is contained in:
Matthew Flatt 2012-01-26 08:55:53 -05:00
parent ab9607b35a
commit 13a5b0c623
6 changed files with 63 additions and 22 deletions

View File

@ -93,7 +93,8 @@
ffi-lib? ffi-lib-name)
(define (get-ffi-lib name [version/s ""]
#:fail [fail #f]
#:get-lib-dirs [get-lib-dirs get-lib-search-dirs])
#:get-lib-dirs [get-lib-dirs get-lib-search-dirs]
#:global? [global? #f])
(cond
[(not name) (ffi-lib name)] ; #f => NULL => open this executable
[(not (or (string? name) (path? name)))
@ -123,7 +124,7 @@
(string-append name0 "." lib-suffix v)
(string-append name0 v "." lib-suffix))))
versions)]
[ffi-lib* (lambda (name) (ffi-lib name #t))])
[ffi-lib* (lambda (name) (ffi-lib name #t global?))])
(or ;; try to look in our library paths first
(and (not absolute?)
(ormap (lambda (dir)
@ -145,8 +146,8 @@
(if fail
(fail)
(if (pair? names)
(ffi-lib (car names))
(ffi-lib name0)))))]))
(ffi-lib (car names) #f global?)
(ffi-lib name0 #f global?)))))]))
(define (get-ffi-lib-internal x)
(if (ffi-lib? x) x (get-ffi-lib x)))

View File

@ -17,7 +17,8 @@ Returns @racket[#t] if @racket[v] is a @deftech{foreign-library value},
@defproc[(ffi-lib [path (or/c path-string? #f)]
[version (or/c string? (listof (or/c string? #f)) #f) #f]
[#:get-lib-dirs get-lib-dirs (-> (listof path?)) get-lib-search-dirs]
[#:fail fail (or/c #f (-> any)) #f])
[#:fail fail (or/c #f (-> any)) #f]
[#:global? global? any/c #f])
any]{
Returns a @tech{foreign-library value} or the result of @racket[fail].
@ -96,6 +97,15 @@ by the run-time system (as described in @|InsideRacket|). The
@racket[version] argument is ignored when @racket[path] is
@racket[#f].
If @racket[path] is not @racket[#f], @racket[global?] is true, and the
operating system supports opening a library in ``global'' mode so that
the library's symbols are used for resolving references from libraries
that are loaded later, then global mode is used to open the
library. Otherwise, the library is opened in ``local'' mode, where the
library's symbols are not made available for future resolution. This
local-versus-global choice does not affect whether the library's
symbols are available via @racket[(ffi-lib #f)].
Due to the way the operating system performs dynamic binding, loaded
libraries are associated with Racket (or DrRacket) for the duration of
the process. Re-evaluating @racket[ffi-lib] (or hitting the

View File

@ -1,3 +1,6 @@
Version 5.2.1.4
Changed ffi-lib to open libraries in local mode by default
Version 5.2.1, January 2012
Changed I/O scheduling to use epoll()/kqueue() when available
Cross-module inline trivial functions, plus map, for-each,

View File

@ -168,6 +168,7 @@ typedef struct ffi_lib_struct {
NON_GCBALE_PTR(void) handle;
Scheme_Object* name;
Scheme_Hash_Table* objects;
int is_global;
} ffi_lib_struct;
#define SCHEME_FFILIBP(x) (SCHEME_TYPE(x)==ffi_lib_tag)
#define MYNAME "ffi-lib?"
@ -199,17 +200,18 @@ END_XFORM_SKIP;
THREAD_LOCAL_DECL(static Scheme_Hash_Table *opened_libs);
/* (ffi-lib filename no-error?) -> ffi-lib */
/* (ffi-lib filename no-error? global?) -> ffi-lib */
#define MYNAME "ffi-lib"
static Scheme_Object *foreign_ffi_lib(int argc, Scheme_Object *argv[])
{
char *name;
Scheme_Object *path, *hashname;
void *handle;
int null_ok = 0;
int null_ok = 0, as_global = 0;
ffi_lib_struct *lib;
if (!(SCHEME_PATH_STRINGP(argv[0]) || SCHEME_FALSEP(argv[0])))
scheme_wrong_type(MYNAME, "string-or-false", 0, argc, argv);
as_global = ((argc > 2) && SCHEME_TRUEP(argv[2]));
/* leave the filename as given, the system will look for it */
/* (`#f' means open the executable) */
path = SCHEME_FALSEP(argv[0]) ? NULL : TO_PATH(argv[0]);
@ -226,7 +228,7 @@ static Scheme_Object *foreign_ffi_lib(int argc, Scheme_Object *argv[])
} else
handle = LoadLibraryW(WIDE_PATH(name));
# else /* WINDOWS_DYNAMIC_LOAD undefined */
handle = dlopen(name, RTLD_NOW | RTLD_GLOBAL);
handle = dlopen(name, RTLD_NOW | (as_global ? RTLD_GLOBAL : RTLD_LOCAL));
# endif /* WINDOWS_DYNAMIC_LOAD */
if (handle == NULL && !null_ok) {
if (argc > 1 && SCHEME_TRUEP(argv[1])) return scheme_false;
@ -248,6 +250,7 @@ static Scheme_Object *foreign_ffi_lib(int argc, Scheme_Object *argv[])
lib->handle = (handle);
lib->name = (argv[0]);
lib->objects = (ht);
lib->is_global = (!name);
scheme_hash_set(opened_libs, hashname, (Scheme_Object*)lib);
/* no dlclose finalizer - since the hash table always keeps a reference */
/* maybe add some explicit unload at some point */
@ -309,7 +312,7 @@ static Scheme_Object *foreign_ffi_obj(int argc, Scheme_Object *argv[])
{
ffi_obj_struct *obj;
void *dlobj;
ffi_lib_struct *lib = NULL;
ffi_lib_struct *lib = NULL, *lib2;
char *dlname;
if (SCHEME_FFILIBP(argv[1]))
lib = (ffi_lib_struct*)argv[1];
@ -361,6 +364,17 @@ static Scheme_Object *foreign_ffi_obj(int argc, Scheme_Object *argv[])
}
# else /* WINDOWS_DYNAMIC_LOAD undefined */
dlobj = dlsym(lib->handle, dlname);
if (!dlobj && lib->is_global) {
/* Try every handle in the table of opened libraries. */
int i;
for (i = opened_libs->size; i--; ) {
if (opened_libs->vals[i]) {
lib2 = (ffi_lib_struct *)opened_libs->vals[i];
dlobj = dlsym(lib2->handle, dlname);
if (dlobj) break;
}
}
}
if (!dlobj) {
const char *err;
err = dlerror();
@ -3430,7 +3444,7 @@ void scheme_init_foreign(Scheme_Env *env)
scheme_add_global("ffi-lib?",
scheme_make_prim_w_arity(foreign_ffi_lib_p, "ffi-lib?", 1, 1), menv);
scheme_add_global("ffi-lib",
scheme_make_prim_w_arity(foreign_ffi_lib, "ffi-lib", 1, 2), menv);
scheme_make_prim_w_arity(foreign_ffi_lib, "ffi-lib", 1, 3), menv);
scheme_add_global("ffi-lib-name",
scheme_make_prim_w_arity(foreign_ffi_lib_name, "ffi-lib-name", 1, 1), menv);
scheme_add_global("ffi-obj?",
@ -3743,7 +3757,7 @@ void scheme_init_foreign(Scheme_Env *env)
scheme_add_global("ffi-lib?",
scheme_make_prim_w_arity((Scheme_Prim *)unimplemented, "ffi-lib?", 1, 1), menv);
scheme_add_global("ffi-lib",
scheme_make_prim_w_arity((Scheme_Prim *)unimplemented, "ffi-lib", 1, 2), menv);
scheme_make_prim_w_arity((Scheme_Prim *)unimplemented, "ffi-lib", 1, 3), menv);
scheme_add_global("ffi-lib-name",
scheme_make_prim_w_arity((Scheme_Prim *)unimplemented, "ffi-lib-name", 1, 1), menv);
scheme_add_global("ffi-obj?",

View File

@ -165,21 +165,23 @@ END_XFORM_SKIP;
/* Library objects */
@cdefstruct[ffi-lib
[handle "NON_GCBALE_PTR(void)"]
[name "Scheme_Object*"]
[objects "Scheme_Hash_Table*"]]
[handle "NON_GCBALE_PTR(void)"]
[name "Scheme_Object*"]
[objects "Scheme_Hash_Table*"]
[is_global "int"]]
THREAD_LOCAL_DECL(static Scheme_Hash_Table *opened_libs);
/* (ffi-lib filename no-error?) -> ffi-lib */
@cdefine[ffi-lib 1 2]{
/* (ffi-lib filename no-error? global?) -> ffi-lib */
@cdefine[ffi-lib 1 3]{
char *name;
Scheme_Object *path, *hashname;
void *handle;
int null_ok = 0;
int null_ok = 0, as_global = 0;
ffi_lib_struct *lib;
if (!(SCHEME_PATH_STRINGP(argv[0]) || SCHEME_FALSEP(argv[0])))
scheme_wrong_type(MYNAME, "string-or-false", 0, argc, argv);
as_global = ((argc > 2) && SCHEME_TRUEP(argv[2]));
/* leave the filename as given, the system will look for it */
/* (`#f' means open the executable) */
path = SCHEME_FALSEP(argv[0]) ? NULL : TO_PATH(argv[0]);
@ -196,7 +198,7 @@ THREAD_LOCAL_DECL(static Scheme_Hash_Table *opened_libs);
} else
handle = LoadLibraryW(WIDE_PATH(name));
}{
handle = dlopen(name, RTLD_NOW | RTLD_GLOBAL);
handle = dlopen(name, RTLD_NOW | (as_global ? RTLD_GLOBAL : RTLD_LOCAL));
}
if (handle == NULL && !null_ok) {
if (argc > 1 && SCHEME_TRUEP(argv[1])) return scheme_false;
@ -213,7 +215,7 @@ THREAD_LOCAL_DECL(static Scheme_Hash_Table *opened_libs);
}
}
ht = scheme_make_hash_table(SCHEME_hash_string);
@cmake["lib" ffi-lib "handle" "argv[0]" "ht"]
@cmake["lib" ffi-lib "handle" "argv[0]" "ht" "!name"]
scheme_hash_set(opened_libs, hashname, (Scheme_Object*)lib);
/* no dlclose finalizer - since the hash table always keeps a reference */
/* maybe add some explicit unload at some point */
@ -240,7 +242,7 @@ THREAD_LOCAL_DECL(static Scheme_Hash_Table *opened_libs);
@cdefine[ffi-obj 2]{
ffi_obj_struct *obj;
void *dlobj;
ffi_lib_struct *lib = NULL;
ffi_lib_struct *lib = NULL, *lib2;
char *dlname;
if (SCHEME_FFILIBP(argv[1]))
lib = (ffi_lib_struct*)argv[1];
@ -292,6 +294,17 @@ THREAD_LOCAL_DECL(static Scheme_Hash_Table *opened_libs);
}
}{
dlobj = dlsym(lib->handle, dlname);
if (!dlobj && lib->is_global) {
/* Try every handle in the table of opened libraries. */
int i;
for (i = opened_libs->size; i--; ) {
if (opened_libs->vals[i]) {
lib2 = (ffi_lib_struct *)opened_libs->vals[i];
dlobj = dlsym(lib2->handle, dlname);
if (dlobj) break;
}
}
}
if (!dlobj) {
const char *err;
err = dlerror();

View File

@ -13,12 +13,12 @@
consistently.)
*/
#define MZSCHEME_VERSION "5.2.1.3"
#define MZSCHEME_VERSION "5.2.1.4"
#define MZSCHEME_VERSION_X 5
#define MZSCHEME_VERSION_Y 2
#define MZSCHEME_VERSION_Z 1
#define MZSCHEME_VERSION_W 3
#define MZSCHEME_VERSION_W 4
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)