Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid
authorPierre Veyre <pierre.veyre@cc.in2p3.fr>
Tue, 18 Mar 2014 07:34:47 +0000 (08:34 +0100)
committerPierre Veyre <pierre.veyre@cc.in2p3.fr>
Tue, 18 Mar 2014 07:34:47 +0000 (08:34 +0100)
25 files changed:
buildtools/Cmake/AddTests.cmake
examples/smpi/energy/f77/sef.f
examples/smpi/energy/f90/sef90.f90
examples/smpi/energy/se.c
include/simgrid/simix.h
include/xbt/misc.h
include/xbt/xbt_os_thread.h
src/mc/mc_memory.c
src/simgrid/sg_config.c
src/simix/smx_context.c
src/simix/smx_context_thread.c
src/simix/smx_global.c
src/simix/smx_private.h
src/xbt/mmalloc/mm_diff.c
src/xbt/mmalloc/mm_module.c
src/xbt/mmalloc/mmorecore.c
src/xbt/xbt_main.c
src/xbt/xbt_os_thread.c
teshsuite/simix/CMakeLists.txt
teshsuite/simix/stack_overflow.c [new file with mode: 0644]
teshsuite/simix/stack_overflow.tesh [new file with mode: 0644]
teshsuite/simix/stack_overflow.xml [new file with mode: 0644]
teshsuite/smpi/mpich3-test/f90/datatype/indtype.f90
teshsuite/smpi/mpich3-test/f90/datatype/structf.f90
teshsuite/xbt/mmalloc_test.c

index e53e83c..719dc51 100644 (file)
@@ -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)
index 51a6ea2..a4c4644 100644 (file)
       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()
 
       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
index f1db81a..833bf73 100644 (file)
@@ -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
index ba969e5..2c4571a 100644 (file)
@@ -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;
 }
index da13e26..02ef86d 100644 (file)
@@ -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 */
index 43fb347..14e48b0 100644 (file)
 
 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 */
index eede122..655c882 100644 (file)
@@ -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;
index aa38112..2253daf 100644 (file)
@@ -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
 }
index 64ebadd..fd2dfd2 100644 (file)
@@ -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",
index 57d84e2..0bfad29 100644 (file)
@@ -13,6 +13,8 @@
 #include "smx_private.h"
 #include "simgrid/sg_config.h"
 #include "internal_config.h"
+#include "simgrid/modelchecker.h"
+#include <sys/mman.h>
 
 #ifdef HAVE_VALGRIND_VALGRIND_H
 # include <valgrind/valgrind.h>
@@ -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);
 }
 
index ea06db0..ee35dfd 100644 (file)
@@ -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);
index 213b41b..6e9174a 100644 (file)
@@ -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);
index 2b62920..7296da4 100644 (file)
@@ -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. */
index 2762185..39cd21c 100644 (file)
@@ -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;
index 7cfde64..08f9de2 100644 (file)
@@ -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 */
index 5ad7cd3..2182cc4 100644 (file)
 
 #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. */
index 26e8dd1..30c1a84 100644 (file)
@@ -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
index ff9d996..f295495 100644 (file)
@@ -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;
index 4c78962..8a22a1a 100644 (file)
@@ -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 (file)
index 0000000..0ae6ffa
--- /dev/null
@@ -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 (file)
index 0000000..2606c83
--- /dev/null
@@ -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 (file)
index 0000000..8ac632a
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version='1.0'?>
+<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid.dtd">
+<platform version="3">
+
+  <!-- The hosts -->
+  <AS  id="AS0"  routing="Full">
+   <host id="Tremblay" power="98.095Mf"/>
+  </AS>
+
+  <!-- The master process (with some arguments) -->
+  <process host="Tremblay" function="master">
+  </process>
+
+</platform>
index 5367f99..123a623 100644 (file)
@@ -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
 
index 71e9735..8227ef0 100644 (file)
@@ -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
 
index a09704d..b9a074c 100644 (file)
@@ -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) {