From: Pierre Veyre Date: Tue, 18 Mar 2014 07:34:47 +0000 (+0100) Subject: Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid X-Git-Tag: v3_11~215 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/1b1016c3ad9e396286bf2c692c92cf5fd567b1d3?hp=31b890c57db2abce779c73765be4021a17f4a040 Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid --- diff --git a/buildtools/Cmake/AddTests.cmake b/buildtools/Cmake/AddTests.cmake index e53e83c54c..719dc51202 100644 --- a/buildtools/Cmake/AddTests.cmake +++ b/buildtools/Cmake/AddTests.cmake @@ -644,6 +644,14 @@ if(NOT enable_memcheck) ADD_TEST(scala-masterslave ${TESH_COMMAND} ${TESH_OPTION} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/scala --setenv classpath=${TESH_CLASSPATH} --cd ${CMAKE_BINARY_DIR}/examples/scala ${CMAKE_HOME_DIRECTORY}/examples/scala/masterslave/masterslave.tesh) endif() + ADD_TEST(stack-overflow-thread ${TESH_COMMAND} ${TESH_OPTION} --cfg contexts/factory:thread --setenv srcdir=${CMAKE_HOME_DIRECTORY}/teshsuite --cd ${CMAKE_BINARY_DIR}/teshsuite ${CMAKE_HOME_DIRECTORY}/teshsuite/simix/stack_overflow.tesh) + if(CONTEXT_UCONTEXT) + ADD_TEST(stack-overflow-ucontext ${TESH_COMMAND} ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv srcdir=${CMAKE_HOME_DIRECTORY}/teshsuite --cd ${CMAKE_BINARY_DIR}/teshsuite ${CMAKE_HOME_DIRECTORY}/teshsuite/simix/stack_overflow.tesh) + endif() + if(HAVE_RAWCTX) + ADD_TEST(stack-overflow-raw ${TESH_COMMAND} ${TESH_OPTION} --cfg contexts/factory:raw --setenv srcdir=${CMAKE_HOME_DIRECTORY}/teshsuite --cd ${CMAKE_BINARY_DIR}/teshsuite ${CMAKE_HOME_DIRECTORY}/teshsuite/simix/stack_overflow.tesh) + endif() + # examples/msg/mc if(HAVE_MC) if(CONTEXT_UCONTEXT) diff --git a/examples/smpi/energy/f77/sef.f b/examples/smpi/energy/f77/sef.f index 51a6ea277a..a4c464448e 100644 --- a/examples/smpi/energy/f77/sef.f +++ b/examples/smpi/energy/f77/sef.f @@ -13,7 +13,16 @@ double precision p, t, e call MPI_Init(ierr) + if (ierr .ne. MPI_SUCCESS) then + print *, 'MPI_Init failed:', ierr + stop 1 + endif call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr) + if (ierr .ne. MPI_SUCCESS) then + print *, 'MPI_Comm_rank failed:', ierr + call MPI_Abort(MPI_COMM_WORLD, 1, ierr) + stop 1 + endif pstates = smpi_get_host_nb_pstates() @@ -44,5 +53,10 @@ end do call MPI_Finalize(ierr) + if (ierr .ne. MPI_SUCCESS) then + print *, 'MPI_Finalize failed:', ierr + call MPI_Abort(MPI_COMM_WORLD, 1, ierr) + stop 1 + endif end program main diff --git a/examples/smpi/energy/f90/sef90.f90 b/examples/smpi/energy/f90/sef90.f90 index f1db81a943..833bf731c2 100644 --- a/examples/smpi/energy/f90/sef90.f90 +++ b/examples/smpi/energy/f90/sef90.f90 @@ -13,7 +13,16 @@ program main double precision p, t, e call MPI_Init(ierr) + if (ierr .ne. MPI_SUCCESS) then + print *, 'MPI_Init failed:', ierr + stop 1 + endif call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr) + if (ierr .ne. MPI_SUCCESS) then + print *, 'MPI_Comm_rank failed:', ierr + call MPI_Abort(MPI_COMM_WORLD, 1, ierr) + stop 1 + endif pstates = smpi_get_host_nb_pstates() @@ -40,5 +49,10 @@ program main end do call MPI_Finalize(ierr) + if (ierr .ne. MPI_SUCCESS) then + print *, 'MPI_Finalize failed:', ierr + call MPI_Abort(MPI_COMM_WORLD, 1, ierr) + stop 1 + endif end program main diff --git a/examples/smpi/energy/se.c b/examples/smpi/energy/se.c index ba969e56ee..2c4571a89a 100644 --- a/examples/smpi/energy/se.c +++ b/examples/smpi/energy/se.c @@ -16,13 +16,20 @@ int main(int argc, char *argv[]) char buf[1024]; char *s; size_t sz, x; + int err; - if (MPI_Init(&argc, &argv) != MPI_SUCCESS) { - fprintf(stderr, "MPI initialization failed!\n"); + err = MPI_Init(&argc, &argv); + if (err != MPI_SUCCESS) { + fprintf(stderr, "MPI_init failed: %d\n", err); exit(EXIT_FAILURE); } - MPI_Comm_rank(MPI_COMM_WORLD, &rank); /* Get id of this process */ + err = MPI_Comm_rank(MPI_COMM_WORLD, &rank); /* Get id of this process */ + if (err != MPI_SUCCESS) { + fprintf(stderr, "MPI_Comm_rank failed: %d", err); + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + exit(EXIT_FAILURE); + } pstates = smpi_get_host_nb_pstates(); @@ -59,5 +66,12 @@ int main(int argc, char *argv[]) MPI_Wtime(), rank, smpi_get_host_consumed_energy()); } - return MPI_Finalize(); + err = MPI_Finalize(); + if (err != MPI_SUCCESS) { + fprintf(stderr, "MPI_Finalize failed: %d\n", err); + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + exit(EXIT_FAILURE); + } + + return EXIT_SUCCESS; } diff --git a/include/simgrid/simix.h b/include/simgrid/simix.h index da13e26b3b..02ef86dda6 100644 --- a/include/simgrid/simix.h +++ b/include/simgrid/simix.h @@ -168,6 +168,8 @@ XBT_PUBLIC(smx_ctx_factory_initializer_t) smx_factory_initializer_to_use; extern char* smx_context_factory_name; extern int smx_context_stack_size; extern int smx_context_stack_size_was_set; +extern int smx_context_guard_size; +extern int smx_context_guard_size_was_set; /* *********************** */ /* Context type definition */ diff --git a/include/xbt/misc.h b/include/xbt/misc.h index 43fb3474a3..14e48b056b 100644 --- a/include/xbt/misc.h +++ b/include/xbt/misc.h @@ -224,6 +224,9 @@ SG_BEGIN_DECL() +/** Cache the size of a memory page for the current system. */ +XBT_PUBLIC_DATA(int) xbt_pagesize; + XBT_PUBLIC(const char *) xbt_procname(void); #define XBT_BACKTRACE_SIZE 10 /* FIXME: better place? Do document */ diff --git a/include/xbt/xbt_os_thread.h b/include/xbt/xbt_os_thread.h index eede122294..655c8826ff 100644 --- a/include/xbt/xbt_os_thread.h +++ b/include/xbt/xbt_os_thread.h @@ -68,6 +68,7 @@ XBT_PUBLIC(void) xbt_os_thread_yield(void); XBT_PUBLIC(void) xbt_os_thread_cancel(xbt_os_thread_t thread); XBT_PUBLIC(void *) xbt_os_thread_getparam(void); XBT_PUBLIC(void) xbt_os_thread_setstacksize(int stack_size); +XBT_PUBLIC(void) xbt_os_thread_setguardsize(int guard_size); /** \brief Thread mutex data type (opaque structure) */ typedef struct xbt_os_mutex_ *xbt_os_mutex_t; diff --git a/src/mc/mc_memory.c b/src/mc/mc_memory.c index aa38112b9b..2253daf402 100644 --- a/src/mc/mc_memory.c +++ b/src/mc/mc_memory.c @@ -30,7 +30,7 @@ void MC_memory_init() raw_heap = NULL; #else /* Create the second region a page after the first one ends + safety gap */ - raw_heap = xbt_mheap_new(-1, (char*)(std_heap) + STD_HEAP_SIZE + getpagesize()); + raw_heap = xbt_mheap_new(-1, (char*)(std_heap) + STD_HEAP_SIZE + xbt_pagesize); xbt_assert(raw_heap != NULL); #endif } diff --git a/src/simgrid/sg_config.c b/src/simgrid/sg_config.c index 64ebadd68e..fd2dfd2aa8 100644 --- a/src/simgrid/sg_config.c +++ b/src/simgrid/sg_config.c @@ -388,6 +388,12 @@ static void _sg_cfg_cb_context_stack_size(const char *name, int pos) smx_context_stack_size = xbt_cfg_get_int(_sg_cfg_set, name) * 1024; } +static void _sg_cfg_cb_context_guard_size(const char *name, int pos) +{ + smx_context_guard_size_was_set = 1; + smx_context_guard_size = xbt_cfg_get_int(_sg_cfg_set, name) * xbt_pagesize; +} + static void _sg_cfg_cb_contexts_nthreads(const char *name, int pos) { SIMIX_context_set_nthreads(xbt_cfg_get_int(_sg_cfg_set, name)); @@ -658,6 +664,14 @@ void sg_config_init(int *argc, char **argv) /* No, it was not set yet (the above setdefault() changed this to 1). */ smx_context_stack_size_was_set = 0; + /* guard size for contexts stacks in memory pages */ + xbt_cfg_register(&_sg_cfg_set, "contexts/guard_size", + "Guard size for contexts stacks in memory pages", + xbt_cfgelm_int, 1, 1, _sg_cfg_cb_context_guard_size, NULL); + xbt_cfg_setdefault_int(_sg_cfg_set, "contexts/guard_size", 1); + /* No, it was not set yet (the above setdefault() changed this to 1). */ + smx_context_guard_size_was_set = 0; + /* number of parallel threads for user processes */ xbt_cfg_register(&_sg_cfg_set, "contexts/nthreads", "Number of parallel threads used to execute user contexts", diff --git a/src/simix/smx_context.c b/src/simix/smx_context.c index 57d84e27e9..0bfad29665 100644 --- a/src/simix/smx_context.c +++ b/src/simix/smx_context.c @@ -13,6 +13,8 @@ #include "smx_private.h" #include "simgrid/sg_config.h" #include "internal_config.h" +#include "simgrid/modelchecker.h" +#include #ifdef HAVE_VALGRIND_VALGRIND_H # include @@ -25,6 +27,8 @@ char* smx_context_factory_name = NULL; /* factory name specified by --cfg=contex smx_ctx_factory_initializer_t smx_factory_initializer_to_use = NULL; int smx_context_stack_size; int smx_context_stack_size_was_set = 0; +int smx_context_guard_size; +int smx_context_guard_size_was_set = 0; #ifdef HAVE_THREAD_LOCAL_STORAGE static __thread smx_context_t smx_current_context_parallel; #else @@ -105,7 +109,28 @@ void SIMIX_context_mod_exit(void) void *SIMIX_context_stack_new(void) { - void *stack = xbt_malloc0(smx_context_stack_size); + void *stack; + + if (smx_context_guard_size > 0 && !MC_is_active()) { + size_t size = smx_context_stack_size + smx_context_guard_size; +#ifdef HAVE_MC + /* Cannot use posix_memalign when HAVE_MC. Align stack by hand, and save the + * pointer returned by xbt_malloc0. */ + char *alloc = xbt_malloc0(size + xbt_pagesize); + stack = alloc - ((uintptr_t)alloc & (xbt_pagesize - 1)) + xbt_pagesize; + *((void **)stack - 1) = alloc; +#else + if (posix_memalign(&stack, xbt_pagesize, size) != 0) + xbt_die("Failed to allocate stack."); +#endif + if (mprotect(stack, smx_context_guard_size, PROT_NONE) == -1) { + XBT_WARN("Failed to protect stack: %s", strerror(errno)); + /* That's not fatal, pursue anyway. */ + } + stack = (char *)stack + smx_context_guard_size; + } else { + stack = xbt_malloc0(smx_context_stack_size); + } #ifdef HAVE_VALGRIND_VALGRIND_H unsigned int valgrind_stack_id = @@ -129,6 +154,18 @@ void SIMIX_context_stack_delete(void *stack) VALGRIND_STACK_DEREGISTER(valgrind_stack_id); #endif + if (smx_context_guard_size > 0 && !MC_is_active()) { + stack = (char *)stack - smx_context_guard_size; + if (mprotect(stack, smx_context_guard_size, + PROT_READ | PROT_WRITE | PROT_EXEC) == -1) { + XBT_WARN("Failed to remove page protection: %s", strerror(errno)); + /* try to pursue anyway */ + } +#ifdef HAVE_MC + /* Retrieve the saved pointer. See SIMIX_context_stack_new above. */ + stack = *((void **)stack - 1); +#endif + } xbt_free(stack); } diff --git a/src/simix/smx_context_thread.c b/src/simix/smx_context_thread.c index ea06db0105..ee35dfdf64 100644 --- a/src/simix/smx_context_thread.c +++ b/src/simix/smx_context_thread.c @@ -94,6 +94,8 @@ smx_ctx_thread_factory_create_context(xbt_main_func_t code, int argc, context->end = xbt_os_sem_init(0); if (smx_context_stack_size_was_set) xbt_os_thread_setstacksize(smx_context_stack_size); + if (smx_context_guard_size_was_set) + xbt_os_thread_setguardsize(smx_context_guard_size); /* create and start the process */ /* NOTE: The first argument to xbt_os_thread_create used to be the process * @@ -151,6 +153,13 @@ static void *smx_ctx_thread_wrapper(void *param) { smx_ctx_thread_t context = (smx_ctx_thread_t) param; + /* Install alternate signal stack, for SIGSEGV handler. */ + stack_t stack; + stack.ss_sp = sigsegv_stack; + stack.ss_size = sizeof sigsegv_stack; + stack.ss_flags = 0; + sigaltstack(&stack, NULL); + /* Tell the maestro we are starting, and wait for its green light */ xbt_os_sem_release(context->end); xbt_os_sem_acquire(context->begin); diff --git a/src/simix/smx_global.c b/src/simix/smx_global.c index 213b41bf16..6e9174ad43 100644 --- a/src/simix/smx_global.c +++ b/src/simix/smx_global.c @@ -42,6 +42,64 @@ static void _XBT_CALL inthandler(int ignored) exit(1); } +static void _XBT_CALL segvhandler(int signum, siginfo_t *siginfo, void *context) +{ + if (siginfo->si_signo == SIGSEGV && siginfo->si_code == SEGV_ACCERR) { + fprintf(stderr, + "Access violation detected. This can result from a stack overflow.\n" + "Try to increase stack size with --cfg=contexts/stack_size (current size is %d KiB).\n", + smx_context_stack_size / 1024); + if (XBT_LOG_ISENABLED(simix_kernel, xbt_log_priority_debug)) { + fprintf(stderr, + "siginfo = {si_signo = %d, si_errno = %d, si_code = %d, si_addr = %p}\n", + siginfo->si_signo, siginfo->si_errno, siginfo->si_code, siginfo->si_addr); + } + } + raise(signum); +} + +char sigsegv_stack[SIGSTKSZ]; /* alternate stack for SIGSEGV handler */ + +/** + * Install signal handler for SIGSEGV. Check that nobody has already installed + * its own handler. For example, the Java VM does this. + */ +static void install_segvhandler(void) +{ + stack_t stack, old_stack; + stack.ss_sp = sigsegv_stack; + stack.ss_size = sizeof sigsegv_stack; + stack.ss_flags = 0; + + if (sigaltstack(&stack, &old_stack) == -1) { + XBT_WARN("Failed to register alternate signal stack: %s", + strerror(errno)); + return; + } + if (!(old_stack.ss_flags & SS_DISABLE)) { + XBT_DEBUG("An alternate stack was already installed (sp=%p, size=%zd, flags=%x). Restore it.", + old_stack.ss_sp, old_stack.ss_size, old_stack.ss_flags); + sigaltstack(&old_stack, NULL); + } + + struct sigaction action, old_action; + action.sa_sigaction = segvhandler; + action.sa_flags = SA_ONSTACK | SA_RESETHAND | SA_SIGINFO; + sigemptyset(&action.sa_mask); + + if (sigaction(SIGSEGV, &action, &old_action) == -1) { + XBT_WARN("Failed to register signal handler for SIGSEGV: %s", + strerror(errno)); + return; + } + if ((old_action.sa_flags & SA_SIGINFO) || old_action.sa_handler != SIG_DFL) { + XBT_DEBUG("A signal handler was already installed for SIGSEGV (%p). Restore it.", + (old_action.sa_flags & SA_SIGINFO) ? + (void*)old_action.sa_sigaction : (void*)old_action.sa_handler); + sigaction(SIGSEGV, &old_action, NULL); + } +} + /********************************* SIMIX **************************************/ XBT_INLINE double SIMIX_timer_next(void) @@ -99,6 +157,9 @@ void SIMIX_global_init(int *argc, char **argv) /* Prepare to display some more info when dying on Ctrl-C pressing */ signal(SIGINT, inthandler); + /* Install SEGV handler */ + install_segvhandler(); + /* register a function to be called by SURF after the environment creation */ sg_platf_init(); sg_platf_postparse_add_cb(SIMIX_post_create_environment); diff --git a/src/simix/smx_private.h b/src/simix/smx_private.h index 2b62920590..7296da4029 100644 --- a/src/simix/smx_private.h +++ b/src/simix/smx_private.h @@ -201,6 +201,8 @@ typedef struct s_smx_action { void SIMIX_context_mod_init(void); void SIMIX_context_mod_exit(void); +XBT_PUBLIC_DATA(char sigsegv_stack[SIGSTKSZ]); + /* We are using the bottom of the stack to save some information, like the * valgrind_stack_id. Define smx_context_usable_stack_size to give the remaining * size for the stack. */ diff --git a/src/xbt/mmalloc/mm_diff.c b/src/xbt/mmalloc/mm_diff.c index 276218593d..39cd21cb80 100644 --- a/src/xbt/mmalloc/mm_diff.c +++ b/src/xbt/mmalloc/mm_diff.c @@ -316,7 +316,7 @@ int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t i1, heaplimit = ((struct mdesc *)heap1)->heaplimit; - s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize(); + s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - xbt_pagesize; heapbase1 = (char *)heap1 + BLOCKSIZE; heapbase2 = (char *)heap2 + BLOCKSIZE; @@ -1372,7 +1372,7 @@ int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2){ /* Heap information */ heaplimit = ((struct mdesc *)heap1)->heaplimit; - s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize(); + s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - xbt_pagesize; heapbase1 = (char *)heap1 + BLOCKSIZE; heapbase2 = (char *)heap2 + BLOCKSIZE; diff --git a/src/xbt/mmalloc/mm_module.c b/src/xbt/mmalloc/mm_module.c index 7cfde64607..08f9de28e8 100644 --- a/src/xbt/mmalloc/mm_module.c +++ b/src/xbt/mmalloc/mm_module.c @@ -323,7 +323,7 @@ void *mmalloc_preinit(void) { int res; if (__mmalloc_default_mdp == NULL) { - unsigned long mask = ~((unsigned long)getpagesize() - 1); + unsigned long mask = ~((unsigned long)xbt_pagesize - 1); void *addr = (void*)(((unsigned long)sbrk(0) + HEAP_OFFSET) & mask); __mmalloc_default_mdp = xbt_mheap_new(-1, addr); /* Fixme? only the default mdp in protected against forks */ diff --git a/src/xbt/mmalloc/mmorecore.c b/src/xbt/mmalloc/mmorecore.c index 5ad7cd37af..2182cc4add 100644 --- a/src/xbt/mmalloc/mmorecore.c +++ b/src/xbt/mmalloc/mmorecore.c @@ -22,15 +22,8 @@ #include "mmprivate.h" -/* Cache the pagesize for the current host machine. Note that if the host - does not readily provide a getpagesize() function, we need to emulate it - elsewhere, not clutter up this file with lots of kluges to try to figure - it out. */ - -static size_t pagesize; - -#define PAGE_ALIGN(addr) (void*) (((long)(addr) + pagesize - 1) & \ - ~(pagesize - 1)) +#define PAGE_ALIGN(addr) (void*) (((long)(addr) + xbt_pagesize - 1) & \ + ~((long)xbt_pagesize - 1)) /* Return MAP_PRIVATE if MDP represents /dev/zero. Otherwise, return MAP_SHARED. */ @@ -65,8 +58,6 @@ void *mmorecore(struct mdesc *mdp, ssize_t size) char buf = 0; /* Single byte to write to extend mapped file */ // fprintf(stderr,"increase %p by %u\n",mdp,size); - if (pagesize == 0) - pagesize = getpagesize(); if (size == 0) { /* Just return the current "break" value. */ diff --git a/src/xbt/xbt_main.c b/src/xbt/xbt_main.c index 26e8dd1a71..30c1a8427a 100644 --- a/src/xbt/xbt_main.c +++ b/src/xbt/xbt_main.c @@ -9,7 +9,7 @@ #include "xbt/misc.h" #include "simgrid_config.h" /* _XBT_WIN32 */ #include "internal_config.h" /* MMALLOC_WANT_OVERRIDE_LEGACY */ - +#include "portable.h" #include "xbt/sysdep.h" #include "xbt/log.h" #include "xbt/dynar.h" @@ -35,6 +35,8 @@ xbt_dynar_t xbt_cmdline = NULL; /* all we got in argv */ int xbt_initialized = 0; int _sg_do_clean_atexit = 1; +int xbt_pagesize; + /* Declare xbt_preinit and xbt_postexit as constructor/destructor of the library. * This is crude and rather compiler-specific, unfortunately. */ @@ -84,6 +86,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, static void xbt_preinit(void) { unsigned int seed = 2147483647; + xbt_pagesize = sysconf(_SC_PAGESIZE); + #ifdef MMALLOC_WANT_OVERRIDE_LEGACY mmalloc_preinit(); #endif diff --git a/src/xbt/xbt_os_thread.c b/src/xbt/xbt_os_thread.c index ff9d996ee3..f29549575c 100644 --- a/src/xbt/xbt_os_thread.c +++ b/src/xbt/xbt_os_thread.c @@ -54,10 +54,9 @@ static xbt_os_thread_t main_thread = NULL; static pthread_key_t xbt_self_thread_key; static int thread_mod_inited = 0; -/* attribute structure to handle pthread stack size changing */ +/* defaults attribute for pthreads */ //FIXME: find where to put this -static pthread_attr_t attr; -static int thread_attr_inited = 0; +static pthread_attr_t thread_attr; /* frees the xbt_os_thread_t corresponding to the current thread */ static void xbt_os_thread_free_thread_data(xbt_os_thread_t thread) @@ -105,11 +104,12 @@ void xbt_os_thread_mod_preinit(void) if ((errcode = pthread_setspecific(xbt_self_thread_key, main_thread))) THROWF(system_error, errcode, "pthread_setspecific failed for xbt_self_thread_key"); - __xbt_running_ctx_fetch = _os_thread_get_running_ctx; __xbt_ex_terminate = _os_thread_ex_terminate; + pthread_attr_init(&thread_attr); + thread_mod_inited = 1; #ifndef HAVE_SEM_INIT @@ -182,7 +182,7 @@ xbt_os_thread_t xbt_os_thread_create(const char *name, XBT_RUNNING_CTX_INITIALIZE(res_thread->running_ctx); res_thread->extra_data = extra_data; - if ((errcode = pthread_create(&(res_thread->t), thread_attr_inited!=0? &attr: NULL, + if ((errcode = pthread_create(&(res_thread->t), &thread_attr, wrapper_start_routine, res_thread))) THROWF(system_error, errcode, "pthread_create failed: %s", strerror(errcode)); @@ -195,35 +195,47 @@ xbt_os_thread_t xbt_os_thread_create(const char *name, void xbt_os_thread_setstacksize(int stack_size) { + size_t alignment[] = { + xbt_pagesize, +#ifdef PTHREAD_STACK_MIN + PTHREAD_STACK_MIN, +#endif + 0 + }; size_t sz; int res; + int i; if (stack_size < 0) xbt_die("stack size %d is negative, maybe it exceeds MAX_INT?", stack_size); sz = stack_size; - pthread_attr_init(&attr); - res = pthread_attr_setstacksize(&attr, sz); + res = pthread_attr_setstacksize(&thread_attr, sz); -#ifdef PTHREAD_STACK_MIN - if (res == EINVAL) { - /* Invalid size, try again with a multiple of PTHREAD_STACK_MIN. */ - size_t rem = sz % PTHREAD_STACK_MIN; + for (i = 0; res == EINVAL && alignment[i] > 0; i++) { + /* Invalid size, try again with next multiple of alignment[i]. */ + size_t rem = sz % alignment[i]; if (rem != 0 || sz == 0) { - size_t sz2 = sz - rem + PTHREAD_STACK_MIN; - XBT_DEBUG("pthread_attr_setstacksize failed for %#zx, try again with %#zx", + size_t sz2 = sz - rem + alignment[i]; + XBT_DEBUG("pthread_attr_setstacksize failed for %zd, try again with %zd", sz, sz2); sz = sz2; - res = pthread_attr_setstacksize(&attr, sz); + res = pthread_attr_setstacksize(&thread_attr, sz); } } -#endif if (res == EINVAL) - XBT_WARN("invalid stack size (maybe too big): %#zx", sz); + XBT_WARN("invalid stack size (maybe too big): %zd", sz); else if (res != 0) - XBT_WARN("unknown error %d in pthread stacksize setting: %#zx", res, sz); - thread_attr_inited = 1; + XBT_WARN("unknown error %d in pthread stacksize setting: %zd", res, sz); +} + +void xbt_os_thread_setguardsize(int guard_size) +{ + size_t sz = guard_size; + int res = pthread_attr_setguardsize(&thread_attr, sz); + if (res) + XBT_WARN("pthread_attr_setguardsize failed (%d) for size: %zd", res, sz); } const char *xbt_os_thread_name(xbt_os_thread_t t) @@ -754,6 +766,11 @@ void xbt_os_thread_setstacksize(int size) stack_size = size; } +void xbt_os_thread_setguardsize(int size) +{ + XBT_WARN("xbt_os_thread_setguardsize is not implemented (%d)", size); +} + const char *xbt_os_thread_name(xbt_os_thread_t t) { return t->name; diff --git a/teshsuite/simix/CMakeLists.txt b/teshsuite/simix/CMakeLists.txt index 4c789622b0..8a22a1af57 100644 --- a/teshsuite/simix/CMakeLists.txt +++ b/teshsuite/simix/CMakeLists.txt @@ -5,20 +5,26 @@ set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}") add_executable(check_defaults check_defaults.c) target_link_libraries(check_defaults simgrid) +add_executable(stack_overflow stack_overflow.c) +target_link_libraries(stack_overflow simgrid) + set(tesh_files ${tesh_files} ${CMAKE_CURRENT_SOURCE_DIR}/factory_raw.tesh ${CMAKE_CURRENT_SOURCE_DIR}/factory_thread.tesh ${CMAKE_CURRENT_SOURCE_DIR}/factory_ucontext.tesh + ${CMAKE_CURRENT_SOURCE_DIR}/stack_overflow.tesh PARENT_SCOPE ) set(xml_files ${xml_files} + ${CMAKE_CURRENT_SOURCE_DIR}/stack_overflow.xml PARENT_SCOPE ) set(teshsuite_src ${teshsuite_src} ${CMAKE_CURRENT_SOURCE_DIR}/check_defaults.c + ${CMAKE_CURRENT_SOURCE_DIR}/stack_overflow.c PARENT_SCOPE ) set(bin_files diff --git a/teshsuite/simix/stack_overflow.c b/teshsuite/simix/stack_overflow.c new file mode 100644 index 0000000000..0ae6ffadaa --- /dev/null +++ b/teshsuite/simix/stack_overflow.c @@ -0,0 +1,58 @@ +/* stack_overflow -- simple program generating a stack overflow */ + +/* Copyright (c) 2014. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "simgrid/platf.h" +#include "simgrid/simix.h" +#include "surf/surfxml_parse.h" +#include "xbt/log.h" + +XBT_LOG_NEW_DEFAULT_CATEGORY(test, "my log messages"); + +static unsigned collatz(unsigned c0, unsigned n) +{ + unsigned x; + if (n == 0) { + x = c0; + } else { + x = collatz(c0, n - 1); + if (x % 2 == 0) + x = x / 2; + else + x = 3 * x + 1; + } + return x; +} + +static int master(int argc, char *argv[]) +{ + XBT_INFO("Launching our nice bugged recursive function..."); + unsigned i = 1; + do { + i *= 2; + unsigned res = collatz(i, i); + XBT_VERB("collatz(%u, %u) returned %u", i, i, res); + } while (i <= 0x80000000u); + return 0; +} + +int main(int argc, char *argv[]) +{ + SIMIX_global_init(&argc, argv); + + if (argc != 2) { + printf("Usage: %s platform_and_deployment.xml\n", argv[0]); + exit(EXIT_FAILURE); + } + + SIMIX_function_register("master", master); + SIMIX_create_environment(argv[1]); + SIMIX_launch_application(argv[1]); + SIMIX_run(); + + return 0; +} diff --git a/teshsuite/simix/stack_overflow.tesh b/teshsuite/simix/stack_overflow.tesh new file mode 100644 index 0000000000..2606c83a4b --- /dev/null +++ b/teshsuite/simix/stack_overflow.tesh @@ -0,0 +1,5 @@ +! expect signal SIGSEGV +$ ./simix/stack_overflow --cfg=contexts/stack_size:96 ${srcdir:=.}/simix/stack_overflow.xml +> [Tremblay:master:(0) 0.000000] [test/INFO] Launching our nice bugged recursive function... +> Access violation detected. This can result from a stack overflow. +> Try to increase stack size with --cfg=contexts/stack_size (current size is 96 KiB). diff --git a/teshsuite/simix/stack_overflow.xml b/teshsuite/simix/stack_overflow.xml new file mode 100644 index 0000000000..8ac632add2 --- /dev/null +++ b/teshsuite/simix/stack_overflow.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/teshsuite/smpi/mpich3-test/f90/datatype/indtype.f90 b/teshsuite/smpi/mpich3-test/f90/datatype/indtype.f90 index 5367f998cc..123a6230e8 100644 --- a/teshsuite/smpi/mpich3-test/f90/datatype/indtype.f90 +++ b/teshsuite/smpi/mpich3-test/f90/datatype/indtype.f90 @@ -23,7 +23,7 @@ call mpi_comm_rank( MPI_COMM_WORLD, rank, ierr ) if (size .lt. 2) then print *, "Must have at least 2 processes" - call MPI_Abort( 1, MPI_COMM_WORLD, ierr ) + call MPI_Abort( MPI_COMM_WORLD, 1, ierr ) stop endif diff --git a/teshsuite/smpi/mpich3-test/f90/datatype/structf.f90 b/teshsuite/smpi/mpich3-test/f90/datatype/structf.f90 index 71e9735422..8227ef06cd 100644 --- a/teshsuite/smpi/mpich3-test/f90/datatype/structf.f90 +++ b/teshsuite/smpi/mpich3-test/f90/datatype/structf.f90 @@ -44,7 +44,7 @@ call mpi_comm_size(MPI_COMM_WORLD, size, ierr ) if (size .lt. 2) then print *, "Must have at least 2 processes" - call MPI_Abort( 1, MPI_COMM_WORLD, ierr ) + call MPI_Abort( MPI_COMM_WORLD, 1, ierr ) stop endif diff --git a/teshsuite/xbt/mmalloc_test.c b/teshsuite/xbt/mmalloc_test.c index a09704de3e..b9a074c648 100644 --- a/teshsuite/xbt/mmalloc_test.c +++ b/teshsuite/xbt/mmalloc_test.c @@ -27,7 +27,7 @@ int main(int argc, char**argv) xbt_init(&argc,argv); XBT_INFO("Allocating a new heap"); - unsigned long mask = ~((unsigned long)getpagesize() - 1); + unsigned long mask = ~((unsigned long)xbt_pagesize - 1); void *addr = (void*)(((unsigned long)sbrk(0) + BUFFSIZE) & mask); heapA = xbt_mheap_new(-1, addr); if (heapA == NULL) {