From 50691212bcebaf1e540fe0371b61be199e4ad761 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sun, 7 Dec 2014 02:56:16 -0500 Subject: [PATCH 1/7] cleanup julia_init options moves all configuration options into jl_compileropts compute the abspath/realpath of file paths in the config to avoid issues with chdir --- Makefile | 4 +- base/client.jl | 3 - base/sysimg.jl | 2 + src/codegen.cpp | 2 +- src/dlload.c | 2 +- src/dump.c | 18 +++-- src/init.c | 164 ++++++++++++++++++++++++++++++++++-------- src/jlapi.c | 38 +++------- src/julia.h | 17 ++--- src/support/dirpath.h | 11 ++- src/support/ios.c | 2 +- src/support/ios.h | 2 +- ui/repl.c | 61 ++-------------- 13 files changed, 178 insertions(+), 148 deletions(-) diff --git a/Makefile b/Makefile index 03d203c8987e7..a905fa679b379 100644 --- a/Makefile +++ b/Makefile @@ -300,8 +300,8 @@ else ifeq ($(OS), Linux) done endif - # Overwrite JL_SYSTEM_IMAGE_PATH in julia binaries - for julia in $(DESTDIR)$(bindir)/julia* ; do \ + # Overwrite JL_SYSTEM_IMAGE_PATH in julia library + for julia in $(DESTDIR)$(private_libdir)/libjulia*.$(SHLIB_EXT) ; do \ $(call spawn,$(build_bindir)/stringreplace $$(strings -t x - $$julia | grep "sys.ji$$" | awk '{print $$1;}' ) "$(private_libdir_rel)/sys.ji" 256 $(call cygpath_w,$$julia)); \ done endif diff --git a/base/client.jl b/base/client.jl index 3518498795e83..e8dc8b0b19009 100644 --- a/base/client.jl +++ b/base/client.jl @@ -372,13 +372,10 @@ import .Terminals import .REPL function _start() - early_init() - try init_parallel() init_bind_addr(ARGS) any(a->(a=="--worker"), ARGS) || init_head_sched() - init_load_path() (quiet,repl,startup,color_set,no_history_file) = process_options(copy(ARGS)) local term diff --git a/base/sysimg.jl b/base/sysimg.jl index 67aa85ba7dd77..a33c5a37a52e6 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -294,6 +294,8 @@ function __init__() reinit_stdio() Multimedia.reinit_displays() # since Multimedia.displays uses STDOUT as fallback fdwatcher_init() + early_init() + init_load_path() end include("precompile.jl") diff --git a/src/codegen.cpp b/src/codegen.cpp index 8fb7738559692..69082212b1dbc 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -869,7 +869,7 @@ static void coverageVisitLine(std::string filename, int line) void write_log_data(logdata_t logData, const char *extension) { - std::string base = std::string(julia_home); + std::string base = std::string(jl_compileropts.julia_home); base = base + "/../share/julia/base/"; logdata_t::iterator it = logData.begin(); for (; it != logData.end(); it++) { diff --git a/src/dlload.c b/src/dlload.c index ef5332696e176..33b6249e34ff2 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -116,7 +116,7 @@ static uv_lib_t *jl_load_dynamic_library_(char *modname, unsigned flags, int thr ext = extensions[i]; path[0] = '\0'; handle->handle = NULL; - if (dl_path[len-1] == PATHSEP) + if (dl_path[len-1] == PATHSEPSTRING[0]) snprintf(path, PATHBUF, "%s%s%s", dl_path, modname, ext); else snprintf(path, PATHBUF, "%s" PATHSEPSTRING "%s%s", dl_path, modname, ext); diff --git a/src/dump.c b/src/dump.c index b9ea91b53e8f4..01f0d502ec0f0 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1305,7 +1305,7 @@ void jl_deserialize_lambdas_from_mod(ios_t *s) extern jl_array_t *jl_module_init_order; -DLLEXPORT void jl_save_system_image(char *fname) +DLLEXPORT void jl_save_system_image(const char *fname) { jl_gc_collect(); jl_gc_collect(); @@ -1339,8 +1339,8 @@ DLLEXPORT void jl_save_system_image(char *fname) for(i=0; i < jl_array_len(jl_module_init_order); i++) { // NULL out any modules that weren't saved jl_value_t *mod = jl_cellref(jl_module_init_order, i); - if (ptrhash_get(&backref_table, mod) == HT_NOTFOUND) - jl_cellset(jl_module_init_order, i, NULL); + (void)mod; + assert(ptrhash_get(&backref_table, mod) != HT_NOTFOUND); } } jl_serialize_value(&f, jl_module_init_order); @@ -1360,11 +1360,10 @@ extern void jl_get_system_hooks(void); extern void jl_get_uv_hooks(); DLLEXPORT -void jl_restore_system_image(char *fname) +void jl_restore_system_image(const char *fname) { ios_t f; - char *fpath = fname; - if (ios_file(&f, fpath, 1, 0, 0, 0) == NULL) { + if (ios_file(&f, fname, 1, 0, 0, 0) == NULL) { JL_PRINTF(JL_STDERR, "System image file \"%s\" not found\n", fname); exit(1); } @@ -1432,14 +1431,13 @@ void jl_restore_system_image(char *fname) //ios_printf(ios_stderr, "backref_list.len = %d\n", backref_list.len); arraylist_free(&backref_list); ios_close(&f); - if (fpath != fname) free(fpath); #ifdef JL_GC_MARKSWEEP if (en) jl_gc_enable(); #endif // restore the value of our "magic" JULIA_HOME variable/constant jl_get_binding_wr(jl_core_module, jl_symbol("JULIA_HOME"))->value = - jl_cstr_to_string(julia_home); + jl_cstr_to_string(jl_compileropts.julia_home); mode = last_mode; jl_update_all_fptrs(); } @@ -1543,7 +1541,7 @@ jl_value_t *jl_uncompress_ast(jl_lambda_info_t *li, jl_value_t *data) } DLLEXPORT -int jl_save_new_module(char *fname, jl_module_t *mod) +int jl_save_new_module(const char *fname, jl_module_t *mod) { ios_t f; if (ios_file(&f, fname, 1, 1, 1, 1) == NULL) { @@ -1583,7 +1581,7 @@ jl_function_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tuple_t *type, jl_function_t *method); DLLEXPORT -jl_module_t *jl_restore_new_module(char *fname) +jl_module_t *jl_restore_new_module(const char *fname) { ios_t f; if (ios_file(&f, fname, 1, 0, 0, 0) == NULL) { diff --git a/src/init.c b/src/init.c index 9519582e2c661..55b2709a9d1a9 100644 --- a/src/init.c +++ b/src/init.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -42,6 +43,12 @@ extern "C" { #endif +#ifdef _MSC_VER +DLLEXPORT char * dirname(char *); +#else +#include +#endif + #ifdef _OS_WINDOWS_ #define WIN32_LEAN_AND_MEAN // Copied from MINGW_FLOAT_H which may not be found due to a collision with the builtin gcc float.h @@ -78,8 +85,11 @@ DLLEXPORT void jlbacktrace(); DLLEXPORT void gdbbacktrace(); DLLEXPORT void gdblookup(ptrint_t ip); -char *julia_home = NULL; -jl_compileropts_t jl_compileropts = { NULL, // build_path +static const char system_image_path[256] = JL_SYSTEM_IMAGE_PATH; + +jl_compileropts_t jl_compileropts = { NULL, // julia_home + NULL, // build_path + system_image_path, // image_file 0, // code_coverage 0, // malloc_log JL_COMPILEROPT_CHECK_BOUNDS_DEFAULT, @@ -729,10 +739,106 @@ kern_return_t catch_exception_raise(mach_port_t exception_port, #endif -void julia_init(char *imageFile) +static char *abspath(const char *in) +{ // compute an absolute path location, so that chdir doesn't change the file reference +#ifndef _OS_WINDOWS_ + char *out = realpath(in, NULL); + if (!out) { + if (in[0] == PATHSEPSTRING[0]) { + out = strdup(in); + } + else { + size_t path_size = PATH_MAX; + size_t len = strlen(in); + char *path = (char*)malloc(PATH_MAX); + if (uv_cwd(path, &path_size)) { + ios_printf(ios_stderr, "fatal error: unexpected error while retrieving current working directory\n"); + exit(1); + } + if (path_size + len + 1 >= PATH_MAX) { + ios_printf(ios_stderr, "fatal error: current working directory path too long\n"); + exit(1); + } + path[path_size-1] = PATHSEPSTRING[0]; + memcpy(path+path_size, in, len+1); + out = strdup(path); + } + } +#else + DWORD n = GetFullPathName(in, 0, NULL, C_NULL); + if (n <= 0) { + ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long or GetFullPathName failed\n"); + exit(1); + } + char *out = (char*)malloc(n); + DWORD m = GetFullPathName(in, n, out, C_NULL); + if (n != m + 1) { + ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long or GetFullPathName failed\n"); + exit(1); + } +#endif + return out; +} + +static void jl_resolve_sysimg_location() +{ // note: if you care about lost memory, you should compare the + // pointers in jl_compileropts before and after calling julia_init() + // and call the appropriate free function on the originals for any that changed + char *free_path = NULL; + if (!jl_compileropts.julia_home) { + jl_compileropts.julia_home = getenv("JULIA_HOME"); + if (!jl_compileropts.julia_home) { + size_t path_size = PATH_MAX; + char *path = (char*)malloc(PATH_MAX); + if (uv_exepath(path, &path_size)) { + ios_printf(ios_stderr, "fatal error: unexpected error while retrieving exepath\n"); + exit(1); + } + if (path_size >= PATH_MAX) { + ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long\n"); + exit(1); + } + free_path = path; + jl_compileropts.julia_home = dirname(path); + } + } + if (jl_compileropts.julia_home) + jl_compileropts.julia_home = abspath(jl_compileropts.julia_home); + if (free_path) { + free(free_path); + free_path = NULL; + } + if (jl_compileropts.image_file) { + if (jl_compileropts.image_file[0] != PATHSEPSTRING[0]) { + if (jl_compileropts.image_file == system_image_path) { + // build time path, relative to JULIA_HOME + char *path = (char*)malloc(PATH_MAX); + int n = snprintf(path, PATH_MAX, "%s" PATHSEPSTRING "%s", + jl_compileropts.julia_home, jl_compileropts.image_file); + if (n >= PATH_MAX || n < 0) { + ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long\n"); + exit(1); + } + free_path = path; + jl_compileropts.image_file = path; + } + } + } + if (jl_compileropts.image_file) + jl_compileropts.image_file = abspath(jl_compileropts.image_file); + if (free_path) { + free(free_path); + free_path = NULL; + } + if (jl_compileropts.build_path) + jl_compileropts.build_path = abspath(jl_compileropts.build_path); +} + +void julia_init() { jl_io_loop = uv_default_loop(); // this loop will internal events (spawning process etc.), // best to call this first, since it also initializes libuv + jl_resolve_sysimg_location(); jl_page_size = jl_getpagesize(); jl_arr_xtralloc_limit = uv_get_total_memory() / 100; // Extra allocation limited to 1% of total RAM jl_find_stack_bottom(); @@ -755,11 +861,11 @@ void julia_init(char *imageFile) if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), (PHANDLE)&hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS)) { - JL_PRINTF(JL_STDERR, "WARNING: failed to access handle to main thread\n"); + ios_printf(ios_stderr, "WARNING: failed to access handle to main thread\n"); } SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); if (!SymInitialize(GetCurrentProcess(), NULL, 1)) { - JL_PRINTF(JL_STDERR, "WARNING: failed to initalize stack walk info\n"); + ios_printf(ios_stderr, "WARNING: failed to initialize stack walk info\n"); } needsSymRefreshModuleList = 0; uv_lib_t jl_dbghelp; @@ -805,7 +911,7 @@ void julia_init(char *imageFile) jl_init_serializer(); - if (!imageFile) { + if (!jl_compileropts.image_file) { jl_core_module = jl_new_module(jl_symbol("Core")); jl_init_intrinsic_functions(); jl_init_primitives(); @@ -823,13 +929,13 @@ void julia_init(char *imageFile) // Core.JULIA_HOME is a "magic" constant, we set it at runtime here // since its value gets excluded from the system image jl_set_const(jl_core_module, jl_symbol("JULIA_HOME"), - jl_cstr_to_string(julia_home)); + jl_cstr_to_string(jl_compileropts.julia_home)); jl_module_export(jl_core_module, jl_symbol("JULIA_HOME")); } - if (imageFile) { + if (jl_compileropts.image_file) { JL_TRY { - jl_restore_system_image(imageFile); + jl_restore_system_image(jl_compileropts.image_file); } JL_CATCH { JL_PRINTF(JL_STDERR, "error during init:\n"); @@ -863,7 +969,6 @@ void julia_init(char *imageFile) jl_current_module = jl_main_module; jl_root_task->current_module = jl_current_module; - #ifndef _OS_WINDOWS_ signal_stack = malloc(sig_stack_size); struct sigaction actf; @@ -872,11 +977,11 @@ void julia_init(char *imageFile) actf.sa_handler = fpe_handler; actf.sa_flags = 0; if (sigaction(SIGFPE, &actf, NULL) < 0) { - JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + JL_PRINTF(JL_STDERR, "fatal error: sigaction: %s\n", strerror(errno)); jl_exit(1); } if (signal(SIGPIPE,SIG_IGN) == SIG_ERR) { - JL_PRINTF(JL_STDERR, "Couldn't set SIGPIPE\n"); + JL_PRINTF(JL_STDERR, "fatal error: Couldn't set SIGPIPE\n"); jl_exit(1); } #if defined (_OS_DARWIN_) @@ -909,7 +1014,7 @@ void julia_init(char *imageFile) ss.ss_size = sig_stack_size; ss.ss_sp = signal_stack; if (sigaltstack(&ss, NULL) < 0) { - JL_PRINTF(JL_STDERR, "sigaltstack: %s\n", strerror(errno)); + JL_PRINTF(JL_STDERR, "fatal error: sigaltstack: %s\n", strerror(errno)); jl_exit(1); } @@ -919,7 +1024,7 @@ void julia_init(char *imageFile) act.sa_sigaction = segv_handler; act.sa_flags = SA_ONSTACK | SA_SIGINFO; if (sigaction(SIGSEGV, &act, NULL) < 0) { - JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + JL_PRINTF(JL_STDERR, "fatal error: sigaction: %s\n", strerror(errno)); jl_exit(1); } #endif // defined(_OS_DARWIN_) @@ -929,49 +1034,50 @@ void julia_init(char *imageFile) act_die.sa_sigaction = sigdie_handler; act_die.sa_flags = SA_SIGINFO; if (sigaction(SIGINFO, &act_die, NULL) < 0) { - JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + JL_PRINTF(JL_STDERR, "fatal error: sigaction: %s\n", strerror(errno)); jl_exit(1); } if (sigaction(SIGBUS, &act_die, NULL) < 0) { - JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + JL_PRINTF(JL_STDERR, "fatal error: sigaction: %s\n", strerror(errno)); jl_exit(1); } if (sigaction(SIGILL, &act_die, NULL) < 0) { - JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + JL_PRINTF(JL_STDERR, "fatal error: sigaction: %s\n", strerror(errno)); jl_exit(1); } if (sigaction(SIGTERM, &act_die, NULL) < 0) { - JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + JL_PRINTF(JL_STDERR, "fatal error: sigaction: %s\n", strerror(errno)); jl_exit(1); } if (sigaction(SIGABRT, &act_die, NULL) < 0) { - JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + JL_PRINTF(JL_STDERR, "fatal error: sigaction: %s\n", strerror(errno)); jl_exit(1); } if (sigaction(SIGQUIT, &act_die, NULL) < 0) { - JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + JL_PRINTF(JL_STDERR, "fatal error: sigaction: %s\n", strerror(errno)); jl_exit(1); } if (sigaction(SIGSYS, &act_die, NULL) < 0) { - JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + JL_PRINTF(JL_STDERR, "fatal error: sigaction: %s\n", strerror(errno)); jl_exit(1); } if (sigaction(SIGPIPE, &act_die, NULL) < 0) { - JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + JL_PRINTF(JL_STDERR, "fatal error: sigaction: %s\n", strerror(errno)); jl_exit(1); } #else // defined(_OS_WINDOWS_) if (signal(SIGFPE, (void (__cdecl *)(int))fpe_handler) == SIG_ERR) { - JL_PRINTF(JL_STDERR, "Couldn't set SIGFPE\n"); + JL_PRINTF(JL_STDERR, "fatal error: Couldn't set SIGFPE\n"); jl_exit(1); } + SetUnhandledExceptionFilter(exception_handler); #endif #ifdef JL_GC_MARKSWEEP jl_gc_enable(); #endif - if (imageFile) + if (jl_compileropts.image_file) jl_init_restored_modules(); jl_install_sigint_handler(); @@ -988,11 +1094,10 @@ DLLEXPORT void jl_install_sigint_handler() act.sa_sigaction = sigint_handler; act.sa_flags = SA_SIGINFO; if (sigaction(SIGINT, &act, NULL) < 0) { - JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + JL_PRINTF(JL_STDERR, "fatal error: sigaction: %s\n", strerror(errno)); jl_exit(1); } #endif - //printf("sigint installed\n"); } extern int asprintf(char **str, const char *fmt, ...); @@ -1002,20 +1107,17 @@ void jl_compile_all(void); DLLEXPORT int julia_trampoline(int argc, char **argv, int (*pmain)(int ac,char *av[])) { -#if defined(_OS_WINDOWS_) - SetUnhandledExceptionFilter(exception_handler); -#endif unsigned char *p = (unsigned char *)&__stack_chk_guard; char a = p[sizeof(__stack_chk_guard)-1]; char b = p[sizeof(__stack_chk_guard)-2]; char c = p[0]; - /* If you have the ability to generate random numbers in your kernel then use them */ + /* If you have the ability to generate random numbers in your kernel then they should be used here */ p[sizeof(__stack_chk_guard)-1] = 255; p[sizeof(__stack_chk_guard)-2] = '\n'; p[0] = 0; JL_SET_STACK_BASE; int ret = pmain(argc, argv); - char *build_path = jl_compileropts.build_path; + const char *build_path = jl_compileropts.build_path; if (build_path) { if (jl_compileropts.compile_enabled == JL_COMPILEROPT_COMPILE_ALL) jl_compile_all(); diff --git a/src/jlapi.c b/src/jlapi.c index a3eb39b7e0000..f3d94b2d2bc6b 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -22,24 +22,6 @@ DLLEXPORT char * __cdecl basename(char *); #include #endif -DLLEXPORT char *jl_locate_sysimg(char *jlhome, char *imgpath) -{ - if (jlhome == NULL) { - char *julia_path = (char*)malloc(512); - size_t path_size = 512; - uv_exepath(julia_path, &path_size); - julia_home = strdup(dirname(julia_path)); - free(julia_path); - } - else { - julia_home = jlhome; - } - char path[512]; - snprintf(path, sizeof(path), "%s%s%s", - julia_home, PATHSEPSTRING, imgpath); - return strdup(path); -} - DLLEXPORT void *jl_eval_string(char *str); int jl_is_initialized(void) { return jl_main_module!=NULL; } @@ -54,22 +36,22 @@ DLLEXPORT void jl_init_with_image(char *julia_home_dir, char *image_relative_pat { if (jl_is_initialized()) return; libsupport_init(); - if (image_relative_path == NULL) - image_relative_path = JL_SYSTEM_IMAGE_PATH; - char *image_file = jl_locate_sysimg(julia_home_dir, image_relative_path); - julia_init(image_file); - jl_set_const(jl_core_module, jl_symbol("JULIA_HOME"), - jl_cstr_to_string(julia_home)); - jl_module_export(jl_core_module, jl_symbol("JULIA_HOME")); - jl_eval_string("Base.early_init()"); + jl_compileropts.julia_home = julia_home_dir; + if (image_relative_path != NULL) + jl_compileropts.image_file = image_relative_path; + julia_init(); + //TODO: these should be part of Multi.__init__() + //currently, we have them here since we may not want them + //getting unconditionally set from Base.__init__() + jl_eval_string("Base.init_parallel()"); + jl_eval_string("Base.init_bind_addr(ARGS)"); jl_eval_string("Base.init_head_sched()"); - jl_eval_string("Base.init_load_path()"); jl_exception_clear(); } DLLEXPORT void jl_init(char *julia_home_dir) { - jl_init_with_image(julia_home_dir, JL_SYSTEM_IMAGE_PATH); + jl_init_with_image(julia_home_dir, NULL); } DLLEXPORT void *jl_eval_string(char *str) diff --git a/src/julia.h b/src/julia.h index 277f0685cd877..f0432ffba4f3e 100644 --- a/src/julia.h +++ b/src/julia.h @@ -856,17 +856,16 @@ DLLEXPORT void jl_exception_clear(void); } // initialization functions -DLLEXPORT void julia_init(char *imageFile); -DLLEXPORT int julia_trampoline(int argc, char *argv[], int (*pmain)(int ac,char *av[])); +DLLEXPORT void julia_init(); DLLEXPORT void jl_init(char *julia_home_dir); DLLEXPORT void jl_init_with_image(char *julia_home_dir, char *image_relative_path); DLLEXPORT int jl_is_initialized(void); -DLLEXPORT extern char *julia_home; +DLLEXPORT int julia_trampoline(int argc, char *argv[], int (*pmain)(int ac,char *av[])); -DLLEXPORT void jl_save_system_image(char *fname); -DLLEXPORT void jl_restore_system_image(char *fname); -DLLEXPORT int jl_save_new_module(char *fname, jl_module_t *mod); -DLLEXPORT jl_module_t *jl_restore_new_module(char *fname); +DLLEXPORT void jl_save_system_image(const char *fname); +DLLEXPORT void jl_restore_system_image(const char *fname); +DLLEXPORT int jl_save_new_module(const char *fname, jl_module_t *mod); +DLLEXPORT jl_module_t *jl_restore_new_module(const char *fname); void jl_init_restored_modules(); // front end interface @@ -1328,7 +1327,9 @@ void show_execution_point(char *filename, int lno); // compiler options ----------------------------------------------------------- typedef struct { - char *build_path; + const char *julia_home; + const char *build_path; + const char *image_file; int8_t code_coverage; int8_t malloc_log; int8_t check_bounds; diff --git a/src/support/dirpath.h b/src/support/dirpath.h index 6cfd965ea0ea8..28fff4ab96def 100644 --- a/src/support/dirpath.h +++ b/src/support/dirpath.h @@ -2,18 +2,15 @@ #define DIRPATH_H #ifdef _OS_WINDOWS_ -#define PATHSEP '\\' #define PATHSEPSTRING "\\" -#define PATHLISTSEP ';' #define PATHLISTSEPSTRING ";" -#define ISPATHSEP(c) ((c)=='/' || (c)=='\\') -#define MAXPATHLEN 1024 +#ifdef _MSC_VER +#define PATH_MAX MAX_PATH +#endif #else -#define PATHSEP '/' #define PATHSEPSTRING "/" -#define PATHLISTSEP ':' #define PATHLISTSEPSTRING ":" -#define ISPATHSEP(c) ((c)=='/') +#define PATH_MAX 1024 #endif #endif diff --git a/src/support/ios.c b/src/support/ios.c index dbab4edbca747..d8bd66c7ede4f 100644 --- a/src/support/ios.c +++ b/src/support/ios.c @@ -836,7 +836,7 @@ static void _ios_init(ios_t *s) /* stream object initializers. we do no allocation. */ -ios_t *ios_file(ios_t *s, char *fname, int rd, int wr, int create, int trunc) +ios_t *ios_file(ios_t *s, const char *fname, int rd, int wr, int create, int trunc) { int flags; int fd; diff --git a/src/support/ios.h b/src/support/ios.h index d5a72fcc79da5..78c6518df92f1 100644 --- a/src/support/ios.h +++ b/src/support/ios.h @@ -100,7 +100,7 @@ DLLEXPORT size_t ios_readprep(ios_t *from, size_t n); /* stream creation */ DLLEXPORT -ios_t *ios_file(ios_t *s, char *fname, int rd, int wr, int create, int trunc); +ios_t *ios_file(ios_t *s, const char *fname, int rd, int wr, int create, int trunc); DLLEXPORT ios_t *ios_mem(ios_t *s, size_t initsize); ios_t *ios_str(ios_t *s, char *str); ios_t *ios_static_buffer(ios_t *s, char *buf, size_t sz); diff --git a/ui/repl.c b/ui/repl.c index 31634902aacbc..49e68a4bbc162 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -4,7 +4,6 @@ */ #include -#include #include #include #include @@ -20,7 +19,6 @@ #ifndef _MSC_VER #include -#include #include #else #include "getopt.h" @@ -34,27 +32,14 @@ #error "JL_SYSTEM_IMAGE_PATH not defined!" #endif -#ifdef _MSC_VER -#define PATH_MAX MAX_PATH -#endif - #ifdef __cplusplus extern "C" { #endif -#ifdef _MSC_VER -DLLEXPORT char * dirname(char *); -#endif - -extern DLLEXPORT char *julia_home; - -char system_image[256] = JL_SYSTEM_IMAGE_PATH; - static int lisp_prompt = 0; static int codecov = JL_LOG_NONE; static int malloclog= JL_LOG_NONE; static char *program = NULL; -char *image_file = NULL; static const char *usage = "julia [options] [program] [args...]\n"; static const char *opts = @@ -111,7 +96,6 @@ void parse_opts(int *argcp, char ***argvp) int c; opterr = 0; int imagepathspecified=0; - image_file = system_image; int skip = 0; int lastind = optind; while ((c = getopt_long(*argcp,*argvp,shortopts,longopts,0)) != -1) { @@ -123,19 +107,19 @@ void parse_opts(int *argcp, char ***argvp) lastind = optind; break; case 'H': - julia_home = strdup(optarg); + jl_compileropts.julia_home = strdup(optarg); break; case 'b': jl_compileropts.build_path = strdup(optarg); if (!imagepathspecified) - image_file = NULL; + jl_compileropts.image_file = NULL; break; case 'J': - image_file = strdup(optarg); + jl_compileropts.image_file = strdup(optarg); imagepathspecified = 1; break; case 'h': - printf("%s%s", usage, opts); + ios_printf(ios_stdout, "%s%s", usage, opts); exit(0); case 'O': jl_compileropts.opt_level = 1; @@ -206,47 +190,14 @@ void parse_opts(int *argcp, char ***argvp) } jl_compileropts.code_coverage = codecov; jl_compileropts.malloc_log = malloclog; - if (!julia_home) { - julia_home = getenv("JULIA_HOME"); - if (julia_home) { - julia_home = strdup(julia_home); - } - else { - char *julia_path = (char*)malloc(PATH_MAX); - size_t path_size = PATH_MAX; - uv_exepath(julia_path, &path_size); - julia_home = strdup(dirname(julia_path)); - free(julia_path); - } - } optind -= skip; *argvp += optind; *argcp -= optind; - if (image_file==NULL && *argcp > 0) { + if (jl_compileropts.image_file==NULL && *argcp > 0) { if (strcmp((*argvp)[0], "-")) { program = (*argvp)[0]; } } - if (image_file) { - if (image_file[0] != PATHSEP) { - uv_stat_t stbuf; - char path[512]; - if (!imagepathspecified) { - // build time path relative to JULIA_HOME - snprintf(path, sizeof(path), "%s%s%s", - julia_home, PATHSEPSTRING, system_image); - image_file = strdup(path); - } - else if (jl_stat(image_file, (char*)&stbuf) != 0) { - // otherwise try julia_home/../lib/julia/%s - snprintf(path, sizeof(path), "%s%s%s", - julia_home, - PATHSEPSTRING ".." PATHSEPSTRING "lib" PATHSEPSTRING "julia" PATHSEPSTRING, - image_file); - image_file = strdup(path); - } - } - } } static int exec_program(void) @@ -384,7 +335,7 @@ int wmain(int argc, wchar_t *argv[], wchar_t *envp[]) jl_lisp_prompt(); return 0; } - julia_init(lisp_prompt ? NULL : image_file); + julia_init(); return julia_trampoline(argc, (char**)argv, true_main); } From 54affdb3f37e8d02c9d6e1806229c4933890a094 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 12 Dec 2014 22:23:21 -0500 Subject: [PATCH 2/7] simplify initialization / startup / embedded / task-switch api --- base/boot.jl | 2 +- base/client.jl | 11 +-- base/exports.jl | 1 + src/ast.c | 2 +- src/codegen.cpp | 5 +- src/dump.c | 12 +-- src/gc.c | 2 +- src/init.c | 77 ++++++---------- src/jl_uv.c | 6 +- src/jlapi.c | 26 +++--- src/julia.h | 49 ++++++----- src/julia_internal.h | 8 +- src/task.c | 204 ++++++++++++++++++++++++++----------------- ui/repl.c | 13 ++- 14 files changed, 221 insertions(+), 197 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index 0ecec7f2fa14c..8c6f984be0770 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -147,7 +147,7 @@ export # method reflection applicable, invoke, method_exists, # constants - JULIA_HOME, nothing, Main, + nothing, Main, # intrinsics module Intrinsics #ccall, cglobal, llvmcall, abs_float, add_float, add_int, and_int, ashr_int, diff --git a/base/client.jl b/base/client.jl index e8dc8b0b19009..db9de86654d25 100644 --- a/base/client.jl +++ b/base/client.jl @@ -356,6 +356,7 @@ function load_machine_file(path::AbstractString) end function early_init() + global const JULIA_HOME = ccall(:jl_get_julia_home, Any, ()) Sys.init_sysinfo() if CPU_CORES > 8 && !("OPENBLAS_NUM_THREADS" in keys(ENV)) && !("OMP_NUM_THREADS" in keys(ENV)) # Prevent openblas from stating to many threads, unless/until specifically requested @@ -409,19 +410,16 @@ function _start() # note: currently IOStream is used for file STDIN if isa(STDIN,File) || isa(STDIN,IOStream) # reading from a file, behave like include - eval(parse_input_line(readall(STDIN))) + eval(Main,parse_input_line(readall(STDIN))) else # otherwise behave repl-like while !eof(STDIN) eval_user_input(parse_input_line(STDIN), true) end end - if have_color - print(color_normal) - end - quit() + else + REPL.run_repl(active_repl) end - REPL.run_repl(active_repl) end catch err display_error(err,catch_backtrace()) @@ -434,7 +432,6 @@ function _start() end println() end - ccall(:uv_atexit_hook, Void, ()) end const atexit_hooks = [] diff --git a/base/exports.jl b/base/exports.jl index 9760a55ad1a36..a17935dce9885 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -163,6 +163,7 @@ export Inf, Inf16, Inf32, + JULIA_HOME, LOAD_PATH, MS_ASYNC, MS_INVALIDATE, diff --git a/src/ast.c b/src/ast.c index f743641d1cf73..544dafd845d28 100644 --- a/src/ast.c +++ b/src/ast.c @@ -114,7 +114,7 @@ static builtinspec_t julia_flisp_ast_ext[] = { { NULL, NULL } }; -DLLEXPORT void jl_init_frontend(void) +void jl_init_frontend(void) { fl_init(4*1024*1024); value_t img = cvalue(iostreamtype, sizeof(ios_t)); diff --git a/src/codegen.cpp b/src/codegen.cpp index 69082212b1dbc..14c6194435d94 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -130,9 +130,8 @@ void __attribute__(()) __stack_chk_fail() #endif { /* put your panic function or similar in here */ - fprintf(stderr, "warning: stack corruption detected\n"); - //assert(0 && "stack corruption detected"); - //abort(); + fprintf(stderr, "fatal error: stack corruption detected\n"); + abort(); // end with abort, since the compiler destroyed the stack upon entry to this function } } diff --git a/src/dump.c b/src/dump.c index 01f0d502ec0f0..ac511abf1e3d7 100644 --- a/src/dump.c +++ b/src/dump.c @@ -452,8 +452,6 @@ static void jl_serialize_module(ios_t *s, jl_module_t *m) jl_serialize_value(s, m->parent); if (ref_only) return; - // set on every startup; don't save value - jl_sym_t *jhsym = jl_symbol("JULIA_HOME"); size_t i; void **table = m->bindings.table; for(i=1; i < m->bindings.size; i+=2) { @@ -461,12 +459,7 @@ static void jl_serialize_module(ios_t *s, jl_module_t *m) jl_binding_t *b = (jl_binding_t*)table[i]; if (b->owner == m || m != jl_main_module) { jl_serialize_value(s, b->name); - if (table[i-1] == jhsym && m == jl_core_module) { - jl_serialize_value(s, NULL); - } - else { - jl_serialize_value(s, b->value); - } + jl_serialize_value(s, b->value); jl_serialize_value(s, b->type); jl_serialize_value(s, b->owner); write_int8(s, (b->constp<<2) | (b->exportp<<1) | (b->imported)); @@ -1435,9 +1428,6 @@ void jl_restore_system_image(const char *fname) #ifdef JL_GC_MARKSWEEP if (en) jl_gc_enable(); #endif - // restore the value of our "magic" JULIA_HOME variable/constant - jl_get_binding_wr(jl_core_module, jl_symbol("JULIA_HOME"))->value = - jl_cstr_to_string(jl_compileropts.julia_home); mode = last_mode; jl_update_all_fptrs(); } diff --git a/src/gc.c b/src/gc.c index 758e5832ba4ec..2c871d09a6cba 100644 --- a/src/gc.c +++ b/src/gc.c @@ -712,7 +712,7 @@ static void gc_mark_task(jl_task_t *ta, int d) gc_mark_stack(jl_pgcstack, offset, d); } else { - offset = (char *)ta->stkbuf - ((char *)ta->stackbase - ta->ssize); + offset = (char *)ta->stkbuf - ((char *)jl_stackbase - ta->ssize); gc_mark_stack(ta->gcstack, offset, d); } #else diff --git a/src/init.c b/src/init.c index 55b2709a9d1a9..0010bf484e882 100644 --- a/src/init.c +++ b/src/init.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) @@ -88,6 +87,7 @@ DLLEXPORT void gdblookup(ptrint_t ip); static const char system_image_path[256] = JL_SYSTEM_IMAGE_PATH; jl_compileropts_t jl_compileropts = { NULL, // julia_home + NULL, // julia_bin NULL, // build_path system_image_path, // image_file 0, // code_coverage @@ -436,7 +436,7 @@ static void jl_uv_exitcleanup_walk(uv_handle_t *handle, void *arg) void jl_write_coverage_data(void); void jl_write_malloc_log(void); -DLLEXPORT void uv_atexit_hook() +DLLEXPORT void jl_atexit_hook() { #if defined(JL_GC_MARKSWEEP) && defined(GC_FINAL_STATS) jl_print_gc_stats(JL_STDERR); @@ -784,57 +784,53 @@ static void jl_resolve_sysimg_location() { // note: if you care about lost memory, you should compare the // pointers in jl_compileropts before and after calling julia_init() // and call the appropriate free function on the originals for any that changed - char *free_path = NULL; + char *free_path = (char*)malloc(PATH_MAX); + size_t path_size = PATH_MAX; + if (uv_exepath(free_path, &path_size)) { + ios_printf(ios_stderr, "fatal error: unexpected error while retrieving exepath\n"); + exit(1); + } + if (path_size >= PATH_MAX) { + ios_printf(ios_stderr, "fatal error: jl_compileropts.julia_bin path too long\n"); + exit(1); + } + jl_compileropts.julia_bin = strdup(free_path); if (!jl_compileropts.julia_home) { jl_compileropts.julia_home = getenv("JULIA_HOME"); if (!jl_compileropts.julia_home) { - size_t path_size = PATH_MAX; - char *path = (char*)malloc(PATH_MAX); - if (uv_exepath(path, &path_size)) { - ios_printf(ios_stderr, "fatal error: unexpected error while retrieving exepath\n"); - exit(1); - } - if (path_size >= PATH_MAX) { - ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long\n"); - exit(1); - } - free_path = path; - jl_compileropts.julia_home = dirname(path); + jl_compileropts.julia_home = dirname(free_path); } } if (jl_compileropts.julia_home) jl_compileropts.julia_home = abspath(jl_compileropts.julia_home); - if (free_path) { - free(free_path); - free_path = NULL; - } + free(free_path); + free_path = NULL; if (jl_compileropts.image_file) { if (jl_compileropts.image_file[0] != PATHSEPSTRING[0]) { if (jl_compileropts.image_file == system_image_path) { // build time path, relative to JULIA_HOME - char *path = (char*)malloc(PATH_MAX); - int n = snprintf(path, PATH_MAX, "%s" PATHSEPSTRING "%s", + free_path = (char*)malloc(PATH_MAX); + int n = snprintf(free_path, PATH_MAX, "%s" PATHSEPSTRING "%s", jl_compileropts.julia_home, jl_compileropts.image_file); if (n >= PATH_MAX || n < 0) { ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long\n"); exit(1); } - free_path = path; - jl_compileropts.image_file = path; + jl_compileropts.image_file = free_path; } } - } - if (jl_compileropts.image_file) - jl_compileropts.image_file = abspath(jl_compileropts.image_file); - if (free_path) { - free(free_path); - free_path = NULL; + if (jl_compileropts.image_file) + jl_compileropts.image_file = abspath(jl_compileropts.image_file); + if (free_path) { + free(free_path); + free_path = NULL; + } } if (jl_compileropts.build_path) jl_compileropts.build_path = abspath(jl_compileropts.build_path); } -void julia_init() +void _julia_init() { jl_io_loop = uv_default_loop(); // this loop will internal events (spawning process etc.), // best to call this first, since it also initializes libuv @@ -926,11 +922,6 @@ void julia_init() jl_get_builtin_hooks(); jl_boot_file_loaded = 1; jl_init_box_caches(); - // Core.JULIA_HOME is a "magic" constant, we set it at runtime here - // since its value gets excluded from the system image - jl_set_const(jl_core_module, jl_symbol("JULIA_HOME"), - jl_cstr_to_string(jl_compileropts.julia_home)); - jl_module_export(jl_core_module, jl_symbol("JULIA_HOME")); } if (jl_compileropts.image_file) { @@ -1105,18 +1096,8 @@ extern void *__stack_chk_guard; void jl_compile_all(void); -DLLEXPORT int julia_trampoline(int argc, char **argv, int (*pmain)(int ac,char *av[])) +DLLEXPORT int julia_save() { - unsigned char *p = (unsigned char *)&__stack_chk_guard; - char a = p[sizeof(__stack_chk_guard)-1]; - char b = p[sizeof(__stack_chk_guard)-2]; - char c = p[0]; - /* If you have the ability to generate random numbers in your kernel then they should be used here */ - p[sizeof(__stack_chk_guard)-1] = 255; - p[sizeof(__stack_chk_guard)-2] = '\n'; - p[0] = 0; - JL_SET_STACK_BASE; - int ret = pmain(argc, argv); const char *build_path = jl_compileropts.build_path; if (build_path) { if (jl_compileropts.compile_enabled == JL_COMPILEROPT_COMPILE_ALL) @@ -1148,10 +1129,6 @@ DLLEXPORT int julia_trampoline(int argc, char **argv, int (*pmain)(int ac,char * ios_printf(ios_stderr,"\nFATAL: failed to create string for .ji build path\n"); } } - p[sizeof(__stack_chk_guard)-1] = a; - p[sizeof(__stack_chk_guard)-2] = b; - p[0] = c; - return ret; } jl_function_t *jl_typeinf_func=NULL; diff --git a/src/jl_uv.c b/src/jl_uv.c index 37615cbd156c8..6b68a895765e5 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -686,14 +686,10 @@ char *jl_bufptr(ios_t *s) return s->buf; } -DLLEXPORT void uv_atexit_hook(); DLLEXPORT void jl_exit(int exitcode) { - /*if (jl_io_loop) { - jl_process_events(&jl_io_loop); - }*/ uv_tty_reset_mode(); - uv_atexit_hook(); + jl_atexit_hook(); exit(exitcode); } diff --git a/src/jlapi.c b/src/jlapi.c index f3d94b2d2bc6b..1f24440ec353b 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -56,12 +56,6 @@ DLLEXPORT void jl_init(char *julia_home_dir) DLLEXPORT void *jl_eval_string(char *str) { -#ifdef COPY_STACKS - int outside_task = (jl_root_task->stackbase == NULL); - if (outside_task) { - JL_SET_STACK_BASE; - } -#endif jl_value_t *r; JL_TRY { jl_value_t *ast = jl_parse_input_line(str); @@ -74,11 +68,6 @@ DLLEXPORT void *jl_eval_string(char *str) //jl_show(jl_stderr_obj(), jl_exception_in_transit); r = NULL; } -#ifdef COPY_STACKS - if (outside_task) { - jl_root_task->stackbase = NULL; - } -#endif return r; } @@ -255,6 +244,21 @@ DLLEXPORT int jl_is_debugbuild(void) #endif } +DLLEXPORT jl_value_t *jl_get_julia_home(void) +{ + return jl_cstr_to_string(jl_compileropts.julia_home); +} + +DLLEXPORT jl_value_t *jl_get_julia_bin(void) +{ + return jl_cstr_to_string(jl_compileropts.julia_bin); +} + +DLLEXPORT jl_value_t *jl_get_image_file(void) +{ + return jl_cstr_to_string(jl_compileropts.image_file); +} + #ifdef __cplusplus } #endif diff --git a/src/julia.h b/src/julia.h index f0432ffba4f3e..d5d0be658786f 100644 --- a/src/julia.h +++ b/src/julia.h @@ -814,7 +814,6 @@ DLLEXPORT jl_value_t *jl_eqtable_get(jl_array_t *h, void *key, jl_value_t *deflt DLLEXPORT int jl_errno(void); DLLEXPORT void jl_set_errno(int e); DLLEXPORT int32_t jl_stat(const char *path, char *statbuf); -DLLEXPORT void NORETURN jl_exit(int status); DLLEXPORT int jl_cpu_cores(void); DLLEXPORT long jl_getpagesize(void); DLLEXPORT long jl_getallocationgranularity(void); @@ -856,11 +855,13 @@ DLLEXPORT void jl_exception_clear(void); } // initialization functions -DLLEXPORT void julia_init(); +DLLEXPORT void julia_init(void); DLLEXPORT void jl_init(char *julia_home_dir); DLLEXPORT void jl_init_with_image(char *julia_home_dir, char *image_relative_path); DLLEXPORT int jl_is_initialized(void); DLLEXPORT int julia_trampoline(int argc, char *argv[], int (*pmain)(int ac,char *av[])); +DLLEXPORT void jl_atexit_hook(void); +DLLEXPORT void NORETURN jl_exit(int status); DLLEXPORT void jl_save_system_image(const char *fname); DLLEXPORT void jl_restore_system_image(const char *fname); @@ -989,22 +990,6 @@ DLLEXPORT jl_value_t *jl_call3(jl_function_t *f, jl_value_t *a, jl_value_t *b, j // interfacing with Task runtime DLLEXPORT void jl_yield(); -DLLEXPORT void jl_handle_stack_start(); - -#ifdef COPY_STACKS -// initialize base context of root task -extern DLLEXPORT jl_jmp_buf jl_base_ctx; -#define JL_SET_STACK_BASE \ - do { \ - int __stk; \ - jl_root_task->stackbase = (char*)&__stk; \ - if (jl_setjmp(jl_base_ctx, 1)) { \ - jl_handle_stack_start(); \ - } \ - } while (0) -#else -#define JL_SET_STACK_BASE -#endif // gc ------------------------------------------------------------------------- @@ -1148,10 +1133,9 @@ typedef struct _jl_task_t { jl_value_t *exception; jl_function_t *start; jl_jmp_buf ctx; - union { - void *stackbase; - void *stack; - }; +#ifndef COPY_STACKS + void *stack; +#endif size_t bufsz; void *stkbuf; size_t ssize; @@ -1328,6 +1312,7 @@ void show_execution_point(char *filename, int lno); typedef struct { const char *julia_home; + const char *julia_bin; const char *build_path; const char *image_file; int8_t code_coverage; @@ -1357,6 +1342,26 @@ extern DLLEXPORT jl_compileropts_t jl_compileropts; #define JL_COMPILEROPT_DUMPBITCODE_ON 1 #define JL_COMPILEROPT_DUMPBITCODE_OFF 2 +extern void *__stack_chk_guard; +#define SET_STACK_CHK_GUARD(a,b,c) do { \ + unsigned char *p = (unsigned char *)&__stack_chk_guard; \ + a = p[sizeof(__stack_chk_guard)-1]; \ + b = p[sizeof(__stack_chk_guard)-2]; \ + c = p[0]; \ + /* If you have the ability to generate random numbers + * in your kernel then they should be used here */ \ + p[sizeof(__stack_chk_guard)-1] = 255; \ + p[sizeof(__stack_chk_guard)-2] = '\n'; \ + p[0] = 0; \ + } while (0) + +#define CLR_STACK_CHK_GUARD(a,b,c) do { \ + unsigned char *p = (unsigned char *)&__stack_chk_guard; \ + p[sizeof(__stack_chk_guard)-1] = a; \ + p[sizeof(__stack_chk_guard)-2] = b; \ + p[0] = c; \ + } while (0) + #ifdef __cplusplus } #endif diff --git a/src/julia_internal.h b/src/julia_internal.h index 9df408979c9be..5b45ec65403cc 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -81,12 +81,16 @@ extern size_t jl_arr_xtralloc_limit; void jl_init_types(void); void jl_init_box_caches(void); -DLLEXPORT void jl_init_frontend(void); +void jl_init_frontend(void); void jl_init_primitives(void); void jl_init_codegen(void); void jl_init_intrinsic_functions(void); void jl_init_tasks(void *stack, size_t ssize); void jl_init_serializer(void); +void _julia_init(void); +#ifdef COPY_STACKS +extern void *jl_stackbase; +#endif void jl_dump_bitcode(char *fname); void jl_dump_objfile(char *fname, int jit_model); @@ -141,6 +145,8 @@ extern uv_lib_t *jl_crtdll_handle; extern uv_lib_t *jl_winsock_handle; #endif +DLLEXPORT void jl_atexit_hook(); + #ifdef __cplusplus } #endif diff --git a/src/task.c b/src/task.c index 4fc7a0764d088..e2945a32c5f4a 100644 --- a/src/task.c +++ b/src/task.c @@ -154,18 +154,24 @@ jl_value_t *jl_exception_in_transit; jl_gcframe_t *jl_pgcstack = NULL; #endif -static void start_task(jl_task_t *t); - #ifdef COPY_STACKS -jl_jmp_buf * volatile jl_jmp_target; -DLLEXPORT jl_jmp_buf jl_base_ctx; +static jl_jmp_buf * volatile jl_jmp_target; + +#if defined(_CPU_X86_64_) || defined(_CPU_X86_) +#define ASM_COPY_STACKS +#endif +void *jl_stackbase; + +#ifndef ASM_COPY_STACKS +static jl_jmp_buf jl_base_ctx; // base context of stack +#endif static void save_stack(jl_task_t *t) { if (t->state == done_sym || t->state == failed_sym) return; volatile int _x; - size_t nb = (char*)t->stackbase - (char*)&_x; + size_t nb = (char*)jl_stackbase - (char*)&_x; char *buf; if (t->stkbuf == NULL || t->bufsz < nb) { buf = (char*)allocb(nb); @@ -180,12 +186,13 @@ static void save_stack(jl_task_t *t) } #if defined(_OS_WINDOWS_) && !defined(_COMPILER_MINGW_) -void __declspec(noinline) restore_stack(jl_task_t *t, jl_jmp_buf *where, char *p) +void __declspec(noinline) #else -void __attribute__((noinline)) restore_stack(jl_task_t *t, jl_jmp_buf *where, char *p) +void __attribute__((noinline)) #endif +restore_stack(jl_task_t *t, jl_jmp_buf *where, char *p) { - char *_x = (char*)t->stackbase - t->ssize; + char *_x = (char*)jl_stackbase - t->ssize; if (!p) { p = _x; if ((char*)&_x > _x) { @@ -202,6 +209,94 @@ void __attribute__((noinline)) restore_stack(jl_task_t *t, jl_jmp_buf *where, ch } #endif +static jl_function_t *task_done_hook_func=NULL; + +static void NORETURN finish_task(jl_task_t *t, jl_value_t *resultval) +{ + if (t->exception != jl_nothing) + t->state = failed_sym; + else + t->state = done_sym; + t->result = resultval; + // TODO: early free of t->stkbuf +#ifdef COPY_STACKS + t->stkbuf = NULL; +#endif + if (task_done_hook_func == NULL) { + task_done_hook_func = (jl_function_t*)jl_get_global(jl_base_module, + jl_symbol("task_done_hook")); + } + if (task_done_hook_func != NULL) { + jl_apply(task_done_hook_func, (jl_value_t**)&t, 1); + } + abort(); +} + +#if defined(_OS_WINDOWS_) && !defined(_COMPILER_MINGW_) +void __declspec(noinline) +#else +void __attribute__((noinline)) +#endif +NORETURN start_task() +{ + // this runs the first time we switch to a task + jl_task_t *t = jl_current_task; + jl_value_t *arg = jl_task_arg_in_transit; + jl_value_t *res; + JL_GC_PUSH1(&arg); + res = jl_apply(t->start, NULL, 0); + JL_GC_POP(); + finish_task(t, res); + abort(); +} + +#ifndef ASM_COPY_STACKS +#if defined(_OS_WINDOWS_) && !defined(_COMPILER_MINGW_) +static void __declspec(noinline) +#else +static void __attribute__((noinline)) +#endif +set_base_ctx(char *__stk) +{ + if (jl_setjmp(jl_base_ctx, 1)) { + start_task(); + } +} +#else +void set_base_ctx(char *__stk) { } +#endif + + +DLLEXPORT void julia_init() +{ // keep this function small, since we want to keep the stack frame + // leading up to this also quite small + _julia_init(); +#ifdef COPY_STACKS + char __stk; + jl_stackbase = (char*)(((uptrint_t)&__stk + sizeof(__stk))&-16); // also ensures stackbase is 16-byte aligned + set_base_ctx(&__stk); // separate function, to record the size of a stack frame +#endif +} + +#ifndef COPY_STACKS +static void init_task(jl_task_t *t) +{ + if (jl_setjmp(t->ctx, 0)) { + start_task(); + } + // this runs when the task is created + ptrint_t local_sp = (ptrint_t)&t; + ptrint_t new_sp = (ptrint_t)t->stack + t->ssize - _frame_offset; +#ifdef _P64 + // SP must be 16-byte aligned + new_sp = new_sp&-16; + local_sp = local_sp&-16; +#endif + memcpy((void*)new_sp, (void*)local_sp, _frame_offset); + rebase_state(&t->ctx, local_sp, new_sp); +} +#endif + static void ctx_switch(jl_task_t *t, jl_jmp_buf *where) { if (t == jl_current_task) @@ -248,7 +343,25 @@ static void ctx_switch(jl_task_t *t, jl_jmp_buf *where) if (t->stkbuf) { restore_stack(t, where, NULL); } else { +#ifdef ASM_COPY_STACKS +#ifdef _CPU_X86_64_ + asm(" movq %0, %%rsp;\n" + " xorq %%rbp, %%rbp;\n" + " push %%rbp;\n" // instead of RSP + " jmp _start_task" // call stack_task with fake stack frame + : : "r"(jl_stackbase-0x10) : ); +#elif defined(_CPU_X86_) + asm(" movl %0, %%esp;\n" + " xorl %%ebp, %%ebp;\n" + " push %%ebp;\n" // instead of ESP + " jmp _start_task" // call stack_task with fake stack frame + : : "r"(jl_stackbase-0x10) : ); +#else +#error ASM_COPY_STACKS not supported on this platform +#endif +#else // ASM_COPY_STACKS jl_longjmp(jl_base_ctx, 1); +#endif } #else jl_longjmp(*where, 1); @@ -368,74 +481,6 @@ jl_value_t *jl_switchto(jl_task_t *t, jl_value_t *arg) return switchto(t); } -static jl_function_t *task_done_hook_func=NULL; - -static void finish_task(jl_task_t *t, jl_value_t *resultval) -{ - if (t->exception != jl_nothing) - t->state = failed_sym; - else - t->state = done_sym; - t->result = resultval; - // TODO: early free of t->stkbuf -#ifdef COPY_STACKS - t->stkbuf = NULL; -#endif - if (task_done_hook_func == NULL) { - task_done_hook_func = (jl_function_t*)jl_get_global(jl_base_module, - jl_symbol("task_done_hook")); - } - if (task_done_hook_func != NULL) { - jl_apply(task_done_hook_func, (jl_value_t**)&t, 1); - } - assert(0); -} - -static void start_task(jl_task_t *t) -{ - // this runs the first time we switch to t - jl_value_t *arg = jl_task_arg_in_transit; - jl_value_t *res; - JL_GC_PUSH1(&arg); - -#ifdef COPY_STACKS - ptrint_t local_sp = (ptrint_t)jl_pgcstack; - // here we attempt to figure out how big our stack frame is, since we - // might need to copy all of it later. this is a bit of a fuzzy guess. - local_sp += sizeof(jl_gcframe_t); - local_sp += 12*sizeof(void*); - t->stackbase = (void*)(local_sp + _frame_offset); -#endif - res = jl_apply(t->start, NULL, 0); - JL_GC_POP(); - finish_task(t, res); - assert(0); -} - -DLLEXPORT void jl_handle_stack_start() -{ - start_task(jl_current_task); -} - -#ifndef COPY_STACKS -static void init_task(jl_task_t *t) -{ - if (jl_setjmp(t->ctx, 0)) { - start_task(t); - } - // this runs when the task is created - ptrint_t local_sp = (ptrint_t)&t; - ptrint_t new_sp = (ptrint_t)t->stack + t->ssize - _frame_offset; -#ifdef _P64 - // SP must be 16-byte aligned - new_sp = new_sp&-16; - local_sp = local_sp&-16; -#endif - memcpy((void*)new_sp, (void*)local_sp, _frame_offset); - rebase_state(&t->ctx, local_sp, new_sp); -} -#endif - ptrint_t bt_data[MAX_BT_SIZE+1]; size_t bt_size = 0; @@ -581,9 +626,8 @@ DLLEXPORT size_t rec_backtrace_ctx(ptrint_t *data, size_t maxsize, unw_context_t do { if (n >= maxsize) break; - if (unw_get_reg(&cursor, UNW_REG_IP, &ip) < 0) { + if (unw_get_reg(&cursor, UNW_REG_IP, &ip) < 0) break; - } data[n++] = ip; } while (unw_step(&cursor) > 0); return n; @@ -602,9 +646,8 @@ size_t rec_backtrace_ctx_dwarf(ptrint_t *data, size_t maxsize, unw_context_t *uc do { if (n >= maxsize) break; - if (unw_get_reg(&cursor, UNW_REG_IP, &ip) < 0) { + if (unw_get_reg(&cursor, UNW_REG_IP, &ip) < 0) break; - } data[n++] = ip; } while (unw_step(&cursor) > 0); return n; @@ -849,7 +892,6 @@ void jl_init_tasks(void *stack, size_t ssize) jl_current_task = (jl_task_t*)allocobj(sizeof(jl_task_t)); jl_current_task->type = (jl_value_t*)jl_task_type; #ifdef COPY_STACKS - jl_current_task->stackbase = NULL; jl_current_task->ssize = 0; // size of saved piece jl_current_task->bufsz = 0; #else diff --git a/ui/repl.c b/ui/repl.c index 49e68a4bbc162..88aa0c479ec09 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -256,7 +256,7 @@ static void print_profile(void) } #endif -int true_main(int argc, char *argv[]) +static int true_main(int argc, char *argv[]) { if (jl_base_module != NULL) { jl_array_t *args = (jl_array_t*)jl_get_global(jl_base_module, jl_symbol("ARGS")); @@ -308,10 +308,11 @@ int true_main(int argc, char *argv[]) JL_PUTS("\n",JL_STDOUT); goto again; } - uv_tty_reset_mode(); return iserr; } +DLLEXPORT extern int julia_save(); + #ifndef _OS_WINDOWS_ int main(int argc, char *argv[]) { @@ -329,6 +330,8 @@ int wmain(int argc, wchar_t *argv[], wchar_t *envp[]) argv[i] = (wchar_t*)arg; } #endif + char a,b,c; + SET_STACK_CHK_GUARD(a,b,c); libsupport_init(); parse_opts(&argc, (char***)&argv); if (lisp_prompt) { @@ -336,7 +339,11 @@ int wmain(int argc, wchar_t *argv[], wchar_t *envp[]) return 0; } julia_init(); - return julia_trampoline(argc, (char**)argv, true_main); + int ret = true_main(argc, (char**)argv); + jl_atexit_hook(); + julia_save(); + CLR_STACK_CHK_GUARD(a,b,c); + return ret; } #ifdef __cplusplus From c37f371c1ea26b0e2a7614a8536d94330546ee18 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 12 Dec 2014 22:54:00 -0500 Subject: [PATCH 3/7] code cleanup --- base/client.jl | 7 ++----- src/codegen.cpp | 2 +- src/disasm.cpp | 2 +- src/dump.c | 6 ++---- src/init.c | 6 +++--- src/julia.expmap | 1 + src/julia.h | 2 +- src/support/dirpath.h | 2 ++ src/task.c | 16 +++++++++------- ui/repl.c | 2 +- 10 files changed, 23 insertions(+), 23 deletions(-) diff --git a/base/client.jl b/base/client.jl index db9de86654d25..27ca40edba1e1 100644 --- a/base/client.jl +++ b/base/client.jl @@ -426,11 +426,8 @@ function _start() println() exit(1) end - if is_interactive - if have_color - print(color_normal) - end - println() + if is_interactive && have_color + print(color_normal) end end diff --git a/src/codegen.cpp b/src/codegen.cpp index 14c6194435d94..fce9e1c848f44 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -121,7 +121,7 @@ extern "C" { #include "builtin_proto.h" -void *__stack_chk_guard = NULL; +DLLEXPORT void *__stack_chk_guard = NULL; #if defined(_OS_WINDOWS_) && !defined(_COMPILER_MINGW_) void __stack_chk_fail() diff --git a/src/disasm.cpp b/src/disasm.cpp index 528d33b88be68..fdd998f84b252 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -482,7 +482,7 @@ void jl_dump_function_asm(const char *Fptr, size_t Fsize, #ifdef LLVM35 if (MCIA->evaluateBranch(Inst, Index, insSize, addr)) #else - if ((addr = MCIA->evaluateBranch(Inst, Index, insSize)) != -1) + if ((addr = MCIA->evaluateBranch(Inst, Index, insSize)) != (uint64_t)-1) #endif DisInfo.insertAddress(addr); } diff --git a/src/dump.c b/src/dump.c index ac511abf1e3d7..3e4cb37701d0a 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1330,10 +1330,8 @@ DLLEXPORT void jl_save_system_image(const char *fname) // save module initialization order if (jl_module_init_order != NULL) { for(i=0; i < jl_array_len(jl_module_init_order); i++) { - // NULL out any modules that weren't saved - jl_value_t *mod = jl_cellref(jl_module_init_order, i); - (void)mod; - assert(ptrhash_get(&backref_table, mod) != HT_NOTFOUND); + // verify that all these modules were saved + assert(ptrhash_get(&backref_table, jl_cellref(jl_module_init_order, i)) != HT_NOTFOUND); } } jl_serialize_value(&f, jl_module_init_order); diff --git a/src/init.c b/src/init.c index 0010bf484e882..ec1181508645e 100644 --- a/src/init.c +++ b/src/init.c @@ -765,13 +765,13 @@ static char *abspath(const char *in) } } #else - DWORD n = GetFullPathName(in, 0, NULL, C_NULL); + DWORD n = GetFullPathName(in, 0, NULL, NULL); if (n <= 0) { ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long or GetFullPathName failed\n"); exit(1); } char *out = (char*)malloc(n); - DWORD m = GetFullPathName(in, n, out, C_NULL); + DWORD m = GetFullPathName(in, n, out, NULL); if (n != m + 1) { ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long or GetFullPathName failed\n"); exit(1); @@ -1096,7 +1096,7 @@ extern void *__stack_chk_guard; void jl_compile_all(void); -DLLEXPORT int julia_save() +DLLEXPORT void julia_save() { const char *build_path = jl_compileropts.build_path; if (build_path) { diff --git a/src/julia.expmap b/src/julia.expmap index 08f54c22f5a0c..40edbbba6a1dc 100644 --- a/src/julia.expmap +++ b/src/julia.expmap @@ -1,6 +1,7 @@ { global: __asan*; + __stack_chk_guard; alloc_*w; allocobj; asprintf; diff --git a/src/julia.h b/src/julia.h index d5d0be658786f..ada5811a7d900 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1342,7 +1342,7 @@ extern DLLEXPORT jl_compileropts_t jl_compileropts; #define JL_COMPILEROPT_DUMPBITCODE_ON 1 #define JL_COMPILEROPT_DUMPBITCODE_OFF 2 -extern void *__stack_chk_guard; +DLLEXPORT extern void *__stack_chk_guard; #define SET_STACK_CHK_GUARD(a,b,c) do { \ unsigned char *p = (unsigned char *)&__stack_chk_guard; \ a = p[sizeof(__stack_chk_guard)-1]; \ diff --git a/src/support/dirpath.h b/src/support/dirpath.h index 28fff4ab96def..e906ddd7521b2 100644 --- a/src/support/dirpath.h +++ b/src/support/dirpath.h @@ -10,7 +10,9 @@ #else #define PATHSEPSTRING "/" #define PATHLISTSEPSTRING ":" +#ifndef PATH_MAX // many platforms don't have a max path, we define one anyways #define PATH_MAX 1024 #endif +#endif #endif diff --git a/src/task.c b/src/task.c index e2945a32c5f4a..cc6f8024f4f79 100644 --- a/src/task.c +++ b/src/task.c @@ -233,9 +233,9 @@ static void NORETURN finish_task(jl_task_t *t, jl_value_t *resultval) } #if defined(_OS_WINDOWS_) && !defined(_COMPILER_MINGW_) -void __declspec(noinline) +static void __declspec(noinline) #else -void __attribute__((noinline)) +static void __attribute__((noinline)) #endif NORETURN start_task() { @@ -348,16 +348,18 @@ static void ctx_switch(jl_task_t *t, jl_jmp_buf *where) asm(" movq %0, %%rsp;\n" " xorq %%rbp, %%rbp;\n" " push %%rbp;\n" // instead of RSP - " jmp _start_task" // call stack_task with fake stack frame - : : "r"(jl_stackbase-0x10) : ); + " jmp %P1;\n" // call stack_task with fake stack frame + " ud2" + : : "r"(jl_stackbase-0x10), "i"(start_task) : "memory" ); #elif defined(_CPU_X86_) asm(" movl %0, %%esp;\n" " xorl %%ebp, %%ebp;\n" " push %%ebp;\n" // instead of ESP - " jmp _start_task" // call stack_task with fake stack frame - : : "r"(jl_stackbase-0x10) : ); + " jmp %P1;\n" // call stack_task with fake stack frame + " ud2" + : : "r"(jl_stackbase-0x10), "i"(start_task) : "memory" ); #else -#error ASM_COPY_STACKS not supported on this platform +#error ASM_COPY_STACKS not supported on this cpu architecture #endif #else // ASM_COPY_STACKS jl_longjmp(jl_base_ctx, 1); diff --git a/ui/repl.c b/ui/repl.c index 88aa0c479ec09..e758b250ba823 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -311,7 +311,7 @@ static int true_main(int argc, char *argv[]) return iserr; } -DLLEXPORT extern int julia_save(); +DLLEXPORT extern void julia_save(); #ifndef _OS_WINDOWS_ int main(int argc, char *argv[]) From 8203538c7f621000cf8fc8fa1509c50c2b83a8dd Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 13 Dec 2014 23:12:19 -0500 Subject: [PATCH 4/7] remove extraneous gc root in start_task --- src/task.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/task.c b/src/task.c index cc6f8024f4f79..6c10904839264 100644 --- a/src/task.c +++ b/src/task.c @@ -241,11 +241,8 @@ NORETURN start_task() { // this runs the first time we switch to a task jl_task_t *t = jl_current_task; - jl_value_t *arg = jl_task_arg_in_transit; jl_value_t *res; - JL_GC_PUSH1(&arg); res = jl_apply(t->start, NULL, 0); - JL_GC_POP(); finish_task(t, res); abort(); } From e2cb463f89ed52aabfc7cb487b5daf2d13dd3e4b Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 13 Dec 2014 23:50:30 -0500 Subject: [PATCH 5/7] allow the user to specify whether the image_file should be interpreted relative to JULIA_HOME or CWD --- src/init.c | 42 +++++++++++++++++++++++++++++------------- src/jlapi.c | 2 +- src/julia.h | 7 ++++++- src/julia_internal.h | 2 +- src/task.c | 4 ++-- ui/repl.c | 4 ++-- 6 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/init.c b/src/init.c index ec1181508645e..cd2288df6d196 100644 --- a/src/init.c +++ b/src/init.c @@ -780,7 +780,7 @@ static char *abspath(const char *in) return out; } -static void jl_resolve_sysimg_location() +static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) { // note: if you care about lost memory, you should compare the // pointers in jl_compileropts before and after calling julia_init() // and call the appropriate free function on the originals for any that changed @@ -806,18 +806,34 @@ static void jl_resolve_sysimg_location() free(free_path); free_path = NULL; if (jl_compileropts.image_file) { - if (jl_compileropts.image_file[0] != PATHSEPSTRING[0]) { - if (jl_compileropts.image_file == system_image_path) { - // build time path, relative to JULIA_HOME - free_path = (char*)malloc(PATH_MAX); - int n = snprintf(free_path, PATH_MAX, "%s" PATHSEPSTRING "%s", - jl_compileropts.julia_home, jl_compileropts.image_file); - if (n >= PATH_MAX || n < 0) { - ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long\n"); - exit(1); + if (rel == JL_IMAGE_JULIA_HOME) { +#ifdef _OS_WINDOWS_ + char c0 = jl_compileropts.image_file[0]; + if (c0 == '/' || c0 == '\\') { + rel = 0; // absolute path relative to %CD% (current drive) + } + else { + int s = strlen(jl_compileropts.image_file); + if (s > 2) { + char c1 = jl_compileropts.image_file[1]; + char c2 = jl_compileropts.image_file[2]; + if (c1 == ':' && (c2 == '/' || c2 == '\\')) rel = 0; // absolute path } - jl_compileropts.image_file = free_path; } +#else + if (jl_compileropts.image_file[0] == '/') rel = 0; // absolute path +#endif + } + if (rel == JL_IMAGE_JULIA_HOME) { + // build time path, relative to JULIA_HOME + free_path = (char*)malloc(PATH_MAX); + int n = snprintf(free_path, PATH_MAX, "%s" PATHSEPSTRING "%s", + jl_compileropts.julia_home, jl_compileropts.image_file); + if (n >= PATH_MAX || n < 0) { + ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long\n"); + exit(1); + } + jl_compileropts.image_file = free_path; } if (jl_compileropts.image_file) jl_compileropts.image_file = abspath(jl_compileropts.image_file); @@ -830,11 +846,11 @@ static void jl_resolve_sysimg_location() jl_compileropts.build_path = abspath(jl_compileropts.build_path); } -void _julia_init() +void _julia_init(JL_IMAGE_SEARCH rel) { jl_io_loop = uv_default_loop(); // this loop will internal events (spawning process etc.), // best to call this first, since it also initializes libuv - jl_resolve_sysimg_location(); + jl_resolve_sysimg_location(rel); jl_page_size = jl_getpagesize(); jl_arr_xtralloc_limit = uv_get_total_memory() / 100; // Extra allocation limited to 1% of total RAM jl_find_stack_bottom(); diff --git a/src/jlapi.c b/src/jlapi.c index 1f24440ec353b..006482e50d921 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -39,7 +39,7 @@ DLLEXPORT void jl_init_with_image(char *julia_home_dir, char *image_relative_pat jl_compileropts.julia_home = julia_home_dir; if (image_relative_path != NULL) jl_compileropts.image_file = image_relative_path; - julia_init(); + julia_init(JL_IMAGE_JULIA_HOME); //TODO: these should be part of Multi.__init__() //currently, we have them here since we may not want them //getting unconditionally set from Base.__init__() diff --git a/src/julia.h b/src/julia.h index ada5811a7d900..f3ad38c84f7a3 100644 --- a/src/julia.h +++ b/src/julia.h @@ -855,7 +855,12 @@ DLLEXPORT void jl_exception_clear(void); } // initialization functions -DLLEXPORT void julia_init(void); +typedef enum { + JL_IMAGE_CWD = 0, + JL_IMAGE_JULIA_HOME = 1, + //JL_IMAGE_LIBJULIA = 2, +} JL_IMAGE_SEARCH; +DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel); DLLEXPORT void jl_init(char *julia_home_dir); DLLEXPORT void jl_init_with_image(char *julia_home_dir, char *image_relative_path); DLLEXPORT int jl_is_initialized(void); diff --git a/src/julia_internal.h b/src/julia_internal.h index 5b45ec65403cc..25a44e873680a 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -87,7 +87,7 @@ void jl_init_codegen(void); void jl_init_intrinsic_functions(void); void jl_init_tasks(void *stack, size_t ssize); void jl_init_serializer(void); -void _julia_init(void); +void _julia_init(JL_IMAGE_SEARCH rel); #ifdef COPY_STACKS extern void *jl_stackbase; #endif diff --git a/src/task.c b/src/task.c index 6c10904839264..01d551509d564 100644 --- a/src/task.c +++ b/src/task.c @@ -264,10 +264,10 @@ void set_base_ctx(char *__stk) { } #endif -DLLEXPORT void julia_init() +DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel) { // keep this function small, since we want to keep the stack frame // leading up to this also quite small - _julia_init(); + _julia_init(rel); #ifdef COPY_STACKS char __stk; jl_stackbase = (char*)(((uptrint_t)&__stk + sizeof(__stk))&-16); // also ensures stackbase is 16-byte aligned diff --git a/ui/repl.c b/ui/repl.c index e758b250ba823..0c18ec88b1144 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -40,6 +40,7 @@ static int lisp_prompt = 0; static int codecov = JL_LOG_NONE; static int malloclog= JL_LOG_NONE; static char *program = NULL; +static int imagepathspecified = 0; static const char *usage = "julia [options] [program] [args...]\n"; static const char *opts = @@ -95,7 +96,6 @@ void parse_opts(int *argcp, char ***argvp) }; int c; opterr = 0; - int imagepathspecified=0; int skip = 0; int lastind = optind; while ((c = getopt_long(*argcp,*argvp,shortopts,longopts,0)) != -1) { @@ -338,7 +338,7 @@ int wmain(int argc, wchar_t *argv[], wchar_t *envp[]) jl_lisp_prompt(); return 0; } - julia_init(); + julia_init(imagepathspecified ? JL_IMAGE_CWD : JL_IMAGE_JULIA_HOME); int ret = true_main(argc, (char**)argv); jl_atexit_hook(); julia_save(); From 9da3b57d9f10affa6039d58860e426f2b96be33d Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sun, 14 Dec 2014 00:09:40 -0500 Subject: [PATCH 6/7] update embedding doc to be consistent with changes to julia_init --- doc/manual/embedding.rst | 18 ++++++++++++++++-- examples/embedding.c | 5 ++++- src/init.c | 1 + 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/doc/manual/embedding.rst b/doc/manual/embedding.rst index a5a0cdb1a73c3..230d3c5b953ad 100644 --- a/doc/manual/embedding.rst +++ b/doc/manual/embedding.rst @@ -18,11 +18,25 @@ We start with a simple C program that initializes Julia and calls some Julia cod int main(int argc, char *argv[]) { + /* optional: randomize the stack guard */ + char a, b, c; + SET_STACK_CHK_GUARD(a,b,c); + + /* required: setup the julia context */ jl_init(NULL); - JL_SET_STACK_BASE; + /* run julia commands */ jl_eval_string("print(sqrt(2.0))"); + /* strongly recommended: notify julia that the + program is about to terminate. this allows + julia time to cleanup pending write requests + and run all finalizers + */ + jl_atexit_hook(); + + /* if the stack guard is set: reset the stack guard */ + CLR_STACK_CHK_GUARD(a,b,c); return 0; } @@ -30,7 +44,7 @@ In order to build this program you have to put the path to the Julia header into gcc -o test -I$JULIA_DIR/include/julia -L$JULIA_DIR/usr/lib -ljulia test.c -Alternatively, look at the ``embedding.c`` program in the julia source tree in the ``examples/`` folder. +Alternatively, look at the ``embedding.c`` program in the julia source tree in the ``examples/`` folder. The file ``ui/repl.c`` program is another simple example of how to set ``jl_compileropts`` options while linking against libjulia. The first thing that has to be done before calling any other Julia C function is to initialize Julia. This is done by calling ``jl_init``, which takes as argument a C string (``const char*``) to the location where Julia is installed. When the argument is ``NULL``, Julia tries to determine the install location automatically. diff --git a/examples/embedding.c b/examples/embedding.c index f9ab53ae9e9e9..fadfd70c997de 100644 --- a/examples/embedding.c +++ b/examples/embedding.c @@ -9,8 +9,9 @@ double my_c_sqrt(double x) int main() { + char a, b, c; + SET_STACK_CHK_GUARD(a,b,c); jl_init(NULL); - JL_SET_STACK_BASE; { // Simple running Julia code @@ -94,5 +95,7 @@ int main() } } + jl_atexit_hook(); + CLR_STACK_CHK_GUARD(a,b,c); return 0; } diff --git a/src/init.c b/src/init.c index cd2288df6d196..335d82d152d5b 100644 --- a/src/init.c +++ b/src/init.c @@ -848,6 +848,7 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) void _julia_init(JL_IMAGE_SEARCH rel) { + libsupport_init(); jl_io_loop = uv_default_loop(); // this loop will internal events (spawning process etc.), // best to call this first, since it also initializes libuv jl_resolve_sysimg_location(rel); From dc8c12addcae4a162b319119295820a14842fb5b Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sun, 14 Dec 2014 00:42:05 -0500 Subject: [PATCH 7/7] some more init cleanup, and comments --- src/init.c | 51 +++++++++++++++++++++++++++++---------------------- ui/Makefile | 1 - 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/init.c b/src/init.c index 335d82d152d5b..8ec4fb1138549 100644 --- a/src/init.c +++ b/src/init.c @@ -739,6 +739,27 @@ kern_return_t catch_exception_raise(mach_port_t exception_port, #endif +static int isabspath(const char *in) +{ +#ifdef _OS_WINDOWS_ + char c0 = in[0]; + if (c0 == '/' || c0 == '\\') { + return 1; // absolute path relative to %CD% (current drive), or UNC + } + else { + int s = strlen(in); + if (s > 2) { + char c1 = in[1]; + char c2 = in[2]; + if (c1 == ':' && (c2 == '/' || c2 == '\\')) return 1; // absolute path + } + } +#else + if (jl_compileropts.image_file[0] == '/') return 1; // absolute path +#endif + return 0; // relative path +} + static char *abspath(const char *in) { // compute an absolute path location, so that chdir doesn't change the file reference #ifndef _OS_WINDOWS_ @@ -781,9 +802,13 @@ static char *abspath(const char *in) } static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) -{ // note: if you care about lost memory, you should compare the - // pointers in jl_compileropts before and after calling julia_init() - // and call the appropriate free function on the originals for any that changed +{ // this function resolves the paths in jl_compileropts to absolute file locations as needed + // and it replaces the pointers to `julia_home`, `julia_bin`, `image_file`, and `build_path` + // it may fail, print an error, and exit(1) if any of these paths are longer than PATH_MAX + // + // note: if you care about lost memory, you should call the appropriate `free()` function + // on the original pointer for each `char*` you've inserted into `jl_compileropts`, after + // calling `julia_init()` char *free_path = (char*)malloc(PATH_MAX); size_t path_size = PATH_MAX; if (uv_exepath(free_path, &path_size)) { @@ -806,25 +831,7 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) free(free_path); free_path = NULL; if (jl_compileropts.image_file) { - if (rel == JL_IMAGE_JULIA_HOME) { -#ifdef _OS_WINDOWS_ - char c0 = jl_compileropts.image_file[0]; - if (c0 == '/' || c0 == '\\') { - rel = 0; // absolute path relative to %CD% (current drive) - } - else { - int s = strlen(jl_compileropts.image_file); - if (s > 2) { - char c1 = jl_compileropts.image_file[1]; - char c2 = jl_compileropts.image_file[2]; - if (c1 == ':' && (c2 == '/' || c2 == '\\')) rel = 0; // absolute path - } - } -#else - if (jl_compileropts.image_file[0] == '/') rel = 0; // absolute path -#endif - } - if (rel == JL_IMAGE_JULIA_HOME) { + if (rel == JL_IMAGE_JULIA_HOME && !isabspath(jl_compileropts.image_file)) { // build time path, relative to JULIA_HOME free_path = (char*)malloc(PATH_MAX); int n = snprintf(free_path, PATH_MAX, "%s" PATHSEPSTRING "%s", diff --git a/ui/Makefile b/ui/Makefile index 181e79fa9ad75..d877f1027c09e 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -58,7 +58,6 @@ julia_res.o: $(JULIAHOME)/contrib/windows/julia.rc $(CROSS_COMPILE)windres $< -O coff -o $@ -DJLVER=$$JLVERi -DJLVER_STR=\\\"$$JLVER\\\" $(build_bindir)/julia$(EXE): julia_res.o $(build_bindir)/julia-debug$(EXE): julia_res.o -JLDFLAGS += julia_res.o endif endif