pike.git / src / main.c

version» Context lines:

pike.git/src/main.c:1: - /*\ - ||| This file a part of Pike, and is copyright by Fredrik Hubinette - ||| Pike is distributed as GPL (General Public License) - ||| See the files COPYING and DISCLAIMER for more information. - \*/ - /**/ + /* + || This file is part of Pike. For copyright information see COPYRIGHT. + || Pike is distributed under GPL, LGPL and MPL. See the file COPYING + || for more information. + */ +    #include "global.h" - RCSID("$Id: main.c,v 1.137 2001/09/24 14:41:37 grubba Exp $"); +    #include "fdlib.h"   #include "backend.h"   #include "module.h"   #include "object.h" - #include "language.h" +    #include "lex.h"   #include "pike_types.h"   #include "builtin_functions.h"   #include "array.h"   #include "stralloc.h"   #include "interpret.h"   #include "pike_error.h"   #include "pike_macros.h"   #include "callback.h"   #include "signal_handler.h"   #include "threads.h"   #include "dynamic_load.h"   #include "gc.h"   #include "multiset.h"   #include "mapping.h"   #include "cpp.h"   #include "main.h"   #include "operators.h"   #include "rbtree.h" - #include "security.h" + #include "pike_security.h"   #include "constants.h"   #include "version.h" -  + #include "program.h" + #include "pike_rusage.h" + #include "module_support.h" + #include "opcodes.h" + #include "bignum.h"    - #if defined(__linux__) && defined(HAVE_DLOPEN) && defined(HAVE_DLFCN_H) + #include "pike_embed.h" +  + #ifdef LIBPIKE + #if defined(HAVE_DLOPEN) && defined(HAVE_DLFCN_H)   #include <dlfcn.h> -  + #undef LIBPIKE   #endif -  + #endif      #include "las.h"    -  + #ifdef HAVE_UNISTD_H + #include <unistd.h> + #endif + #ifdef HAVE_ERRNO_H   #include <errno.h> -  + #endif      #ifdef HAVE_LOCALE_H   #include <locale.h>   #endif      #include "time_stuff.h"      #ifdef HAVE_SYS_RESOURCE_H   #include <sys/resource.h>   #endif    - #ifdef TRY_USE_MMX - #include <mmx.h> - int try_use_mmx; - #endif -  +    /* Define this to trace the execution of main(). */   /* #define TRACE_MAIN */    -  + #ifdef PIKE_EXTRA_DEBUG + #define TRACE_MAIN + #endif /* PIKE_EXTRA_DEBUG */ +    #ifdef TRACE_MAIN   #define TRACE(X) fprintf X   #else /* !TRACE_MAIN */   #define TRACE(X)   #endif /* TRACE_MAIN */    - char *master_file; - char **ARGV; + /* +  * Code searching for master & libpike. +  */    - PMOD_EXPORT int debug_options=0; - PMOD_EXPORT int runtime_options=0; - PMOD_EXPORT int d_flag=0; - PMOD_EXPORT int c_flag=0; - PMOD_EXPORT int t_flag=0; - PMOD_EXPORT int default_t_flag=0; - PMOD_EXPORT int a_flag=0; - PMOD_EXPORT int l_flag=0; - PMOD_EXPORT int p_flag=0; - #if defined(YYDEBUG) || defined(PIKE_DEBUG) - extern int yydebug; - #endif /* YYDEBUG || PIKE_DEBUG */ - static long instructions_left; + #define MASTER_COOKIE1 "(#*&)@(*&$" + #define MASTER_COOKIE2 "Master Cookie:"    - #define MASTER_COOKIE "(#*&)@(*&$Master Cookie:" + #define MASTER_COOKIE MASTER_COOKIE1 MASTER_COOKIE2      #ifndef MAXPATHLEN   #define MAXPATHLEN 32768   #endif    - char master_location[MAXPATHLEN * 2] = MASTER_COOKIE; + static char master_location[MAXPATHLEN * 2] = MASTER_COOKIE;    - static void time_to_exit(struct callback *cb,void *tmp,void *ignored) + static void set_master(const char *file)   { -  if(instructions_left-- < 0) -  { -  push_int(0); -  f_exit(1); +  if (strlen(file) >= MAXPATHLEN*2 - CONSTANT_STRLEN(MASTER_COOKIE)) { +  fprintf(stderr, "Too long path to master: \"%s\" (limit:%"PRINTPTRDIFFT"d)\n", +  file, MAXPATHLEN*2 - CONSTANT_STRLEN(MASTER_COOKIE)); +  exit(1);    } -  +  strcpy(master_location + CONSTANT_STRLEN(MASTER_COOKIE), file);   }    - #ifdef PROFILING - static unsigned int samples[8200]; - long record; -  - static void sample_stack(struct callback *cb,void *tmp,void *ignored) - { -  long stack_size=( ((char *)&cb) - Pike_interpreter.stack_bottom) * STACK_DIRECTION; -  stack_size>>=10; -  stack_size++; -  if(stack_size<0) stack_size=0; -  if(stack_size >= (long)NELEM(samples)) stack_size=NELEM(samples)-1; -  samples[stack_size]++; - #ifdef PIKE_DEBUG -  if(stack_size > record) -  { -  extern void gdb_break_on_stack_record(long); -  gdb_break_on_stack_record(stack_size); -  record=stack_size; -  } - #endif - } -  - #ifdef PIKE_DEBUG - void gdb_break_on_stack_record(long stack_size) - { -  ; - } - #endif - #endif -  - static struct callback_list post_master_callbacks; -  - PMOD_EXPORT struct callback *add_post_master_callback(callback_func call, -  void *arg, -  callback_func free_func) - { -  return add_to_callback(&post_master_callbacks, call, arg, free_func); - } -  -  - static struct callback_list exit_callbacks; -  - PMOD_EXPORT struct callback *add_exit_callback(callback_func call, -  void *arg, -  callback_func free_func) - { -  return add_to_callback(&exit_callbacks, call, arg, free_func); - } -  +    #ifdef __NT__   static void get_master_key(HKEY cat)   {    HKEY k;    char buffer[4096];    DWORD len=sizeof(buffer)-1,type=REG_SZ;       if(RegOpenKeyEx(cat, -  (LPCTSTR)("SOFTWARE\\Idonex\\Pike\\" +  (LPCTSTR)("SOFTWARE\\Pike\\"    DEFINETOSTR(PIKE_MAJOR_VERSION)    "." -  DEFINETOSTR(PIKE_MINOR_VERSION)), +  DEFINETOSTR(PIKE_MINOR_VERSION) +  "." +  DEFINETOSTR(PIKE_BUILD_VERSION)),    0,KEY_READ,&k)==ERROR_SUCCESS)    {    if(RegQueryValueEx(k,    "PIKE_MASTER",    0,    &type,    buffer,    &len)==ERROR_SUCCESS)    { -  dmalloc_accept_leak( master_file=strdup(buffer) ); +  /* FIXME: Look at len? UNICODE? */ +  set_master(buffer);    }    RegCloseKey(k);    }   }   #endif /* __NT__ */    - int dbm_main(int argc, char **argv) + static void set_default_master(const char *bin_name)   { -  JMP_BUF back; -  int e, num; +  char *mp = master_location + CONSTANT_STRLEN (MASTER_COOKIE); +  + #ifdef HAVE_GETENV +  if(!*mp && getenv("PIKE_MASTER")) { +  set_master(getenv("PIKE_MASTER")); +  } + #endif +  + #ifdef __NT__ +  if(!*mp) get_master_key(HKEY_CURRENT_USER); +  if(!*mp) get_master_key(HKEY_LOCAL_MACHINE); + #endif +  +  if(!*mp && strncmp(DEFAULT_MASTER, "NONE/", 5)) +  { +  SNPRINTF (mp, sizeof (master_location) - CONSTANT_STRLEN (MASTER_COOKIE), +  DEFAULT_MASTER, +  PIKE_MAJOR_VERSION, +  PIKE_MINOR_VERSION, +  PIKE_BUILD_VERSION); +  } +  + #ifdef __NT__ +  if (!(*mp == '/' || *mp == '\\' || (isalpha (*mp) && mp[1] == ':'))) { +  char exepath[MAXPATHLEN]; +  if (!GetModuleFileName (NULL, exepath, _MAX_PATH)) +  fprintf (stderr, "Failed to get path to exe file: %d\n", +  GetLastError()); +  else { +  char tmp[MAXPATHLEN * 2]; +  char *p = strrchr (exepath, '\\'); +  if (p) *p = 0; +  SNPRINTF (tmp, sizeof (tmp), "%s/%s", exepath, mp); +  strncpy (mp, tmp, +  sizeof (master_location) - CONSTANT_STRLEN (MASTER_COOKIE)); +  } +  } + #else +  if (!*mp) { +  /* Attempt to find a master via the path to the binary. */ +  /* Note: We assume that MAXPATHLEN is > 18 characters. */ +  if (strlen(bin_name) < (2*MAXPATHLEN - +  CONSTANT_STRLEN(MASTER_COOKIE "master.pike"))) {    char *p; -  struct array *a; - #ifdef DECLARE_ENVIRON -  extern char **environ; +  strcpy(mp, bin_name); +  p = strrchr(mp, '/'); +  if (!p) p = mp; +  else p++; +  strcpy(p, "master.pike"); +  } +  }   #endif    -  TRACE((stderr, "dbm_main()\n")); +  TRACE((stderr, "Default master at \"%s\"...\n", mp)); + }    -  /* Attempt to make sure stderr is unbuffered. */ - #ifdef HAVE_SETVBUF -  setvbuf(stderr, NULL, _IONBF, 0); - #else /* !HAVE_SETVBUF */ - #ifdef HAVE_SETBUF -  setbuf(stderr, NULL); - #endif /* HAVE_SETBUF */ - #endif /* HAVE_SETVBUF */ + #ifdef LIBPIKE + static char libpike_file[MAXPATHLEN * 2]; + static void *libpike;    -  TRACE((stderr, "Init CPU lib...\n")); + typedef void (*modfun)(void); + #ifdef NO_CAST_TO_FUN + /* Function pointers can't be casted to scalar pointers according to +  * ISO-C (probably to support true Harward achitecture machines). +  */ + static modfun CAST_TO_FUN(void *ptr) + { +  union { +  void *ptr; +  modfun fun; +  } u; +  u.ptr = ptr; +  return u.fun; + } + #else /* !NO_CAST_TO_FUN */ + #define CAST_TO_FUN(X) ((modfun)X) + #endif /* NO_CAST_TO_FUN */    -  init_pike_cpulib(); + static void (*init_pike_var)(const char **argv, const char *file); + static void (*init_pike_runtime_var)(void (*exit_cb)(int)); + static void (*add_predefine_var)(char *s); + #endif /* LIBPIKE */    - #ifdef TRY_USE_MMX -  TRACE((stderr, "Init MMX...\n")); + static void find_lib_dir(int argc, char **argv) + { +  int e;    -  try_use_mmx=mmx_ok(); - #endif - #ifdef OWN_GETHRTIME - /* initialize our own gethrtime conversion /Mirar */ -  TRACE((stderr, "Init gethrtime...\n")); +  TRACE((stderr, "find_lib_dir...\n"));    -  own_gethrtime_init(); - #endif +  set_default_master(argv[0]);    -  ARGV=argv; +  for(e=1; e<argc; e++) +  { +  TRACE((stderr, "Parse argument %d:\"%s\"...\n", e, argv[e]));    -  TRACE((stderr, "Main init...\n")); +  if(argv[e][0] != '-') break;    -  fd_init(); +  switch(argv[e][1])    { -  extern void init_mapping_blocks(void); -  extern void init_callable_blocks(void); -  extern void init_gc_frame_blocks(void); -  extern void init_pike_frame_blocks(void); -  extern void init_node_s_blocks(void); -  extern void init_object_blocks(void); -  extern void init_callback_blocks(void); +  default: +  break;    -  init_mapping_blocks(); -  init_callable_blocks(); -  init_gc_frame_blocks(); -  init_pike_frame_blocks(); -  init_node_s_blocks(); -  init_object_blocks(); -  init_callback_blocks(); -  init_rbtree(); +  case 'm': +  if(argv[e][2]) +  { +  set_master(argv[e]+2); +  }else{ +  e++; +  if(e >= argc) +  { +  fprintf(stderr,"Missing argument to -m\n"); +  exit(1);    } -  +  set_master(argv[e]); +  } +  break;    - #ifdef SHARED_NODES -  TRACE((stderr, "Init shared nodes...\n")); +  case 's': +  if((!argv[e][2]) || +  ((argv[e][2] == 's') && !argv[e][3])) { +  e++; +  } +  break;    -  node_hash.table = malloc(sizeof(node *)*32831); -  if (!node_hash.table) { -  fatal("Out of memory!\n"); +  case 'q': +  if(!argv[e][2]) e++; +  break;    } -  MEMSET(node_hash.table, 0, sizeof(node *)*32831); -  node_hash.size = 32831; - #endif /* SHARED_NODES */ +  }    - #ifdef HAVE_SETLOCALE - #ifdef LC_NUMERIC -  setlocale(LC_NUMERIC, "C"); + #ifdef LIBPIKE +  { +  char *p; +  char *dir; +  memcpy(libpike_file, master_location + CONSTANT_STRLEN(MASTER_COOKIE), +  sizeof(master_location) - CONSTANT_STRLEN(MASTER_COOKIE)); +  for (p = dir = libpike_file; *p; p++) { +  if ((*p == '/') + #ifdef __NT__ +  || (*p == '\\') + #endif /* __NT__ */ +  ) +  dir = p+1; +  } +  if ((dir + CONSTANT_STRLEN("pike.so")) >= libpike_file + 2*MAXPATHLEN) { +  /* Not likely to happen as long as MASTER_COOKIE is longer than "pike.so". +  */ +  fprintf(stderr, "Too long path to pike.so.\n"); +  exit(1); +  } +  /* Don't forget the NUL! */ +  memcpy(dir, "pike.so", CONSTANT_STRLEN("pike.so") + 1); +  } + #endif /* LIBPIKE */ + } +  + int main(int argc, char **argv) + { +  JMP_BUF back; +  int e, num; +  char *p; +  + #ifdef PIKE_EXTRA_DEBUG + #ifdef HAVE_SIGNAL +  if (sizeof(void *) == 8) { +  /* 64-bit Solaris 10 in Xenofarm fails with SIGPIPE. +  * Force a core dump. +  */ +  signal(SIGPIPE, abort); +  }   #endif - #ifdef LC_CTYPE -  setlocale(LC_CTYPE, ""); +    #endif - #ifdef LC_TIME -  setlocale(LC_TIME, "C"); +  + #ifdef HAVE_MALLOPT +  TRACE((stderr, "Init malloc...\n")); +  +  /* The malloc implementation in recent glibc (eg Linux) +  * defaults to using one arena / thread. This means that +  * memory once allocated from one thread can't later be +  * allocated by another thread. +  * +  * cf [bug 6045] and http://sourceware.org/bugzilla/show_bug.cgi?id=11261 +  * +  * We try to alleviate the problem by reducing the number +  * of arenas as much as possible. +  */ +  + #ifdef M_ARENA_TEST +  /* NB: Some versions of glibc don't support setting M_ARENA_TEST to 0. */ +  /* Note also that the test is inverted since mallopt returns 0 on success. */ +  mallopt(M_ARENA_TEST, 0) && mallopt(M_ARENA_TEST, 1);   #endif - #ifdef LC_COLLATE -  setlocale(LC_COLLATE, ""); + #ifdef M_ARENA_MAX +  mallopt(M_ARENA_MAX, 1);   #endif - #ifdef LC_MESSAGES -  setlocale(LC_MESSAGES, ""); - #endif - #endif + #endif /* HAVE_MALLOPT */       TRACE((stderr, "Init master...\n"));    -  master_file = 0; +  find_lib_dir(argc, argv);    - #ifdef HAVE_GETENV -  if(getenv("PIKE_MASTER")) -  master_file = getenv("PIKE_MASTER"); - #endif + #ifdef LIBPIKE + #ifdef HAVE_DLINIT +  if (!dlinit()) { +  fprintf(stderr, "dlinit failed.\n"); +  exit(1); +  } + #endif /* HAVE_DLINIT */    -  if(master_location[CONSTANT_STRLEN(MASTER_COOKIE)]) -  master_file=master_location + CONSTANT_STRLEN(MASTER_COOKIE); +  if (!(libpike = dlopen(libpike_file, RTLD_NOW))) { +  const char *err = dlerror(); +  if (!err) err = "Unknown reason."; +  fprintf(stderr, "Failed to open %s: %s\n", libpike_file, err); +  exit(1); +  }    - #if __NT__ -  if(!master_file) get_master_key(HKEY_CURRENT_USER); -  if(!master_file) get_master_key(HKEY_LOCAL_MACHINE); - #endif + #define LOOKUP(symbol) do { \ +  if (!(PIKE_CONCAT(symbol, _var) = \ +  CAST_TO_FUN(dlsym(libpike, TOSTR(symbol)))) && \ +  !(PIKE_CONCAT(symbol, _var) = \ +  CAST_TO_FUN(dlsym(libpike, "_" TOSTR(symbol))))) { \ +  fprintf(stderr, "Missing symbol in %s: " TOSTR(symbol) "\n", \ +  libpike_file); \ +  dlclose(libpike); \ +  exit(1); \ +  } \ +  } while(0)    -  if(!master_file) -  { -  sprintf(master_location,DEFAULT_MASTER, -  PIKE_MAJOR_VERSION, -  PIKE_MINOR_VERSION, -  PIKE_BUILD_VERSION); -  master_file=master_location; -  } +  LOOKUP(init_pike); + #define init_pike init_pike_var +  LOOKUP(init_pike_runtime); + #define init_pike_runtime init_pike_runtime_var +  LOOKUP(add_predefine); + #define add_predefine add_predefine_var    -  TRACE((stderr, "Default master at \"%s\"...\n", master_file)); + #endif /* LIBPIKE */    -  +  TRACE((stderr, "init_pike()\n")); +  +  init_pike(argv, master_location + CONSTANT_STRLEN(MASTER_COOKIE)); +     for(e=1; e<argc; e++)    {    TRACE((stderr, "Parse argument %d:\"%s\"...\n", e, argv[e]));       if(argv[e][0]=='-')    {    for(p=argv[e]+1; *p;)    {    switch(*p)    {    case 'D':    add_predefine(p+1);    p+=strlen(p);    break;       case 'm':    if(p[1])    { -  master_file=p+1; +     p+=strlen(p);    }else{    e++;    if(e >= argc)    {    fprintf(stderr,"Missing argument to -m\n");    exit(1);    } -  master_file=argv[e]; +     p+=strlen(p);    }    break;       case 's':    if(!p[1])    {    e++;    if(e >= argc)    {
pike.git/src/main.c:376:    e++;    if(e >= argc)    {    fprintf(stderr,"Missing argument to -q\n");    exit(1);    }    p=argv[e];    }else{    p++;    } -  instructions_left=STRTOL(p,&p,0); +  set_pike_evaluator_limit(STRTOL(p, &p, 0));    p+=strlen(p); -  add_to_callback(&evaluator_callbacks, -  time_to_exit, -  0,0); -  +     break;       case 'd':    more_d_flags:    switch(p[1])    {    case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    d_flag+=STRTOL(p+1,&p,10);    break;       case 'c':    p++; - #if defined(YYDEBUG) || defined(PIKE_DEBUG) + #if (defined(YYDEBUG) && (YYDEBUG==1)) && defined(PIKE_DEBUG)    yydebug++; - #endif /* YYDEBUG || PIKE_DEBUG */ + #endif /* YYDEBUG && PIKE_DEBUG */    break;       case 's': -  debug_options|=DEBUG_SIGNALS; +  set_pike_debug_options(DEBUG_SIGNALS, DEBUG_SIGNALS);    p++;    goto more_d_flags;       case 't': -  debug_options|=NO_TAILRECURSION; +  set_pike_debug_options(NO_TAILRECURSION, NO_TAILRECURSION);    p++;    goto more_d_flags;       case 'g': -  debug_options|=GC_RESET_DMALLOC; +  set_pike_debug_options(GC_RESET_DMALLOC, GC_RESET_DMALLOC);    p++;    goto more_d_flags;       case 'p': -  debug_options|=NO_PEEP_OPTIMIZING; +  set_pike_debug_options(NO_PEEP_OPTIMIZING, NO_PEEP_OPTIMIZING);    p++;    goto more_d_flags;    -  +  case 'T': +  set_pike_debug_options(ERRORCHECK_MUTEXES, ERRORCHECK_MUTEXES); +  p++; +  goto more_d_flags; +  +  case 'L': +  set_pike_debug_options (WINDOWS_ERROR_DIALOGS, +  WINDOWS_ERROR_DIALOGS); +  p++; +  goto more_d_flags; +     default:    d_flag += (p[0] == 'd');    p++;    }    break;       case 'r':    more_r_flags:    switch(p[1])    {    case 't': -  runtime_options |= RUNTIME_CHECK_TYPES; +  set_pike_runtime_options(RUNTIME_CHECK_TYPES, RUNTIME_CHECK_TYPES);    p++;    goto more_r_flags;       case 'T': -  runtime_options |= RUNTIME_STRICT_TYPES; +  set_pike_runtime_options(RUNTIME_STRICT_TYPES, +  RUNTIME_STRICT_TYPES);    p++;    goto more_r_flags;       default:    p++;    break;    }    break;       case 'a':    if(p[1]>='0' && p[1]<='9')    a_flag+=STRTOL(p+1,&p,10);    else    a_flag++,p++;    break;       case 't': -  if(p[1]>='0' && p[1]<='9') -  t_flag+=STRTOL(p+1,&p,10); -  else -  t_flag++,p++; -  default_t_flag = t_flag; +  more_t_flags: +  switch (p[1]) { +  case '0': case '1': case '2': case '3': case '4': +  case '5': case '6': case '7': case '8': case '9': +  Pike_interpreter.trace_level+=STRTOL(p+1,&p,10);    break;    -  +  case 'g': +  gc_trace++; +  p++; +  goto more_t_flags; +  +  default: +  if (p[0] == 't') +  Pike_interpreter.trace_level++; +  p++; +  } +  default_t_flag = Pike_interpreter.trace_level; +  break; +     case 'p':    if(p[1]=='s')    { - #ifdef PROFILING -  add_to_callback(&evaluator_callbacks, -  sample_stack, -  0,0); +  pike_enable_stack_profiling();    p+=strlen(p); - #endif +     }else{    if(p[1]>='0' && p[1]<='9')    p_flag+=STRTOL(p+1,&p,10);    else    p_flag++,p++;    }    break;       case 'l':    if(p[1]>='0' && p[1]<='9')
pike.git/src/main.c:494:       default:    p+=strlen(p);    }    }    }else{    break;    }    }    - #if !defined(RLIMIT_NOFILE) && defined(RLIMIT_OFILE) - #define RLIMIT_NOFILE RLIMIT_OFILE + #ifndef PIKE_MUTEX_ERRORCHECK +  if (set_pike_debug_options(0,0) & ERRORCHECK_MUTEXES) +  fputs ("Warning: -dT (error checking mutexes) not supported on this system.\n", +  stderr);   #endif -  +  if (d_flag) +  set_pike_debug_options(ERRORCHECK_MUTEXES, ERRORCHECK_MUTEXES);    -  TRACE((stderr, "Init C stack...\n")); -  -  Pike_interpreter.stack_top = (char *)&argv; -  -  /* Adjust for anything already pushed on the stack. -  * We align on a 64 KB boundary. -  * Thus we at worst, lose 64 KB stack. + #ifdef HAVE_SETERRORMODE +  if (!(debug_options & WINDOWS_ERROR_DIALOGS)) { +  /* This avoids popups when LoadLibrary fails to find a dll.    * -  * We have to do it this way since some compilers don't like -  * & and | on pointers, and casting to an integer type is -  * too unsafe (consider 64-bit systems). -  */ - #if STACK_DIRECTION < 0 -  /* Equvivalent with |= 0xffff */ -  Pike_interpreter.stack_top += (~((size_t)Pike_interpreter.stack_top)) & 0xffff; - #else /* STACK_DIRECTION >= 0 */ -  /* Equvivalent with &= ~0xffff */ -  Pike_interpreter.stack_top -= ( ((size_t)Pike_interpreter.stack_top)) & 0xffff; - #endif /* STACK_DIRECTION < 0 */ -  - #ifdef PROFILING -  Pike_interpreter.stack_bottom=Pike_interpreter.stack_top; +  * Note that the popup is the _only_ way to see which dll (loaded +  * indirectly by dependencies from the one in the LoadLibrary +  * call) that Windows didn't find. :( Hence the -rl runtime option +  * to turn it on. +  * +  * Note: This setting is process global. */ +  SetErrorMode (SEM_FAILCRITICALERRORS | +  /* Maybe set this too? Don't know exactly when it +  * has effect. /mast */ +  /*SEM_NOOPENFILEERRORBOX | */ +  SetErrorMode (0)); +  }   #endif    - #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_STACK) -  { -  struct rlimit lim; -  if(!getrlimit(RLIMIT_STACK, &lim)) -  { - #ifdef RLIM_INFINITY -  if(lim.rlim_cur == RLIM_INFINITY) -  lim.rlim_cur=1024*1024*32; - #endif +  init_pike_runtime(exit);    - #ifdef Pike_INITIAL_STACK_SIZE -  if(lim.rlim_cur > Pike_INITIAL_STACK_SIZE) -  lim.rlim_cur=Pike_INITIAL_STACK_SIZE; - #endif -  - #if defined(__linux__) && defined(PIKE_THREADS) -  /* This is a really really *stupid* limit in glibc 2.x -  * which is not detectable since __pthread_initial_thread_bos -  * went static. On a stupidity-scale from 1-10, this rates a -  * solid 11. - Hubbe +  /* NOTE: Reuse master_location here to avoid duplicates of +  * the MASTER_COOKIE string in the binary.    */ -  if(lim.rlim_cur > 2*1024*1024) lim.rlim_cur=2*1024*1024; - #endif +  add_pike_string_constant("__master_cookie", +  master_location, CONSTANT_STRLEN(MASTER_COOKIE));    - #if defined(_AIX) && defined(__ia64) -  /* getrlimit() on AIX 5L/IA64 Beta 3 reports 32MB by default, -  * even though the stack is just 8MB. -  */ -  if (lim.rlim_cur > 8*1024*1024) { -  lim.rlim_cur = 8*1024*1024; -  } - #endif /* _AIX && __ia64 */ -  - #if STACK_DIRECTION < 0 -  Pike_interpreter.stack_top -= lim.rlim_cur; - #else /* STACK_DIRECTION >= 0 */ -  Pike_interpreter.stack_top += lim.rlim_cur; - #endif /* STACK_DIRECTION < 0 */ -  - #if defined(__linux__) && defined(HAVE_DLOPEN) && defined(HAVE_DLFCN_H) +  if(SETJMP(back))    { -  char ** bos_location; -  void *handle; -  /* damn this is ugly -Hubbe */ -  if((handle=dlopen(0, RTLD_LAZY))) +  if(throw_severity == THROW_EXIT || throw_severity == THROW_THREAD_EXIT)    { -  bos_location=dlsym(handle,"__pthread_initial_thread_bos"); -  dlclose(handle); +  num=throw_value.u.integer; +  }else{ +  if (TYPEOF(throw_value) == T_OBJECT && +  throw_value.u.object->prog == master_load_error_program && +  !get_master()) { +  /* Report this specific error in a nice way. Since there's no +  * master it'd be reported with a raw error dump otherwise. */ +  struct generic_error_struct *err;    -  if(bos_location && *bos_location && -  (*bos_location - Pike_interpreter.stack_top) *STACK_DIRECTION < 0) -  { -  Pike_interpreter.stack_top=*bos_location; -  } -  } -  } - #else - #ifdef HAVE_PTHREAD_INITIAL_THREAD_BOS -  { -  extern char * __pthread_initial_thread_bos; -  /* Linux glibc threads are limited to a 4 Mb stack -  * __pthread_initial_thread_bos is the actual limit -  */ +  dynamic_buffer buf; +  dynbuf_string s; +  struct svalue t;    -  if(__pthread_initial_thread_bos && -  (__pthread_initial_thread_bos - Pike_interpreter.stack_top) *STACK_DIRECTION < 0) -  { -  Pike_interpreter.stack_top=__pthread_initial_thread_bos; -  } -  } - #endif /* HAVE_PTHREAD_INITIAL_THREAD_BOS */ - #endif /* __linux__ && HAVE_DLOPEN && HAVE_DLFCN_H */ +  move_svalue (Pike_sp++, &throw_value); +  mark_free_svalue (&throw_value); +  err = (struct generic_error_struct *) +  get_storage (Pike_sp[-1].u.object, generic_error_program);    - #if STACK_DIRECTION < 0 -  Pike_interpreter.stack_top += 8192 * sizeof(char *); - #else /* STACK_DIRECTION >= 0 */ -  Pike_interpreter.stack_top -= 8192 * sizeof(char *); - #endif /* STACK_DIRECTION < 0 */ +  SET_SVAL(t, PIKE_T_STRING, 0, string, err->error_message);    -  +  init_buf(&buf); +  describe_svalue(&t,0,0); +  s=complex_free_buf(&buf);    - #ifdef STACK_DEBUG -  fprintf(stderr, "1: C-stack: 0x%08p - 0x%08p, direction:%d\n", -  &argv, Pike_interpreter.stack_top, STACK_DIRECTION); - #endif /* STACK_DEBUG */ +  fputs(s.str, stderr); +  free(s.str);    } -  } - #else /* !HAVE_GETRLIMIT || !RLIMIT_STACK */ -  /* 128 MB seems a bit extreme, most OS's seem to have their limit at ~8MB */ -  Pike_interpreter.stack_top += STACK_DIRECTION * (1024*1024 * 8 - 8192 * sizeof(char *)); - #ifdef STACK_DEBUG -  fprintf(stderr, "2: C-stack: 0x%08p - 0x%08p, direction:%d\n", -  &argv, Pike_interpreter.stack_top, STACK_DIRECTION); - #endif /* STACK_DEBUG */ - #endif /* HAVE_GETRLIMIT && RLIMIT_STACK */ -  - #if 0 - #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) -  { -  struct rlimit lim; -  long tmp; -  if(!getrlimit(RLIMIT_NOFILE, &lim)) -  { - #ifdef RLIM_INFINITY -  if(lim.rlim_max == RLIM_INFINITY) -  lim.rlim_max=MAX_OPEN_FILEDESCRIPTORS; - #endif -  tmp=MINIMUM(lim.rlim_max, MAX_OPEN_FILEDESCRIPTORS); -  lim.rlim_cur=tmp; -  setrlimit(RLIMIT_NOFILE, &lim); -  } -  } - #endif - #endif -  -  TRACE((stderr, "Init time...\n")); -  -  GETTIMEOFDAY(&current_time); -  -  TRACE((stderr, "Init interpreter...\n")); -  -  init_shared_string_table(); -  init_interpreter(); -  init_types(); -  init_cpp(); -  init_lex(); -  init_program(); -  init_object(); -  low_th_init(); -  -  TRACE((stderr, "Init modules...\n")); -  -  init_modules(); -  -  TRACE((stderr, "Init master...\n")); -  -  master(); -  call_callback(& post_master_callbacks, 0); -  free_callback_list(& post_master_callbacks); -  -  TRACE((stderr, "Call master->_main()...\n")); -  -  if(SETJMP(back)) -  { -  if(throw_severity == THROW_EXIT) -  { -  num=throw_value.u.integer; -  }else{ +  else    call_handle_error();    num=10;    }    }else{ -  +  struct object *m; +     back.severity=THROW_EXIT;    -  a=allocate_array_no_init(argc,0); -  for(num=0;num<argc;num++) -  { -  ITEM(a)[num].u.string=make_shared_string(argv[num]); -  ITEM(a)[num].type=T_STRING; -  } -  push_array(a); +  if ((m = load_pike_master())) { +  TRACE((stderr, "Call master->_main()...\n"));    -  for(num=0;environ[num];num++); -  a=allocate_array_no_init(num,0); -  for(num=0;environ[num];num++) -  { -  ITEM(a)[num].u.string=make_shared_string(environ[num]); -  ITEM(a)[num].type=T_STRING; -  } -  push_array(a); +  pike_push_argv(argc, argv);    -  apply(master(),"_main",2); +  apply(m, "_main", 1);    pop_stack();    num=0; -  +  } else { +  num = -1;    } -  +  }    UNSETJMP(back);    -  TRACE((stderr, "Exit %s...\n", num)); +  TRACE((stderr, "Exit %d...\n", num));       pike_do_exit(num);    return num; /* avoid warning */   } -  - #undef ATTRIBUTE - #define ATTRIBUTE(X) -  - DECLSPEC(noreturn) void pike_do_exit(int num) ATTRIBUTE((noreturn)) - { -  call_callback(&exit_callbacks, (void *)0); -  free_callback_list(&exit_callbacks); -  -  exit_modules(); -  - #ifdef DEBUG_MALLOC -  { -  extern void cleanup_memhdrs(void); -  cleanup_memhdrs(); -  } - #endif -  -  - #ifdef PROFILING -  { -  int q; -  for(q=0;q<(long)NELEM(samples);q++) -  if(samples[q]) -  fprintf(stderr,"STACK WAS %4d Kb %12u times\n",q-1,samples[q]); -  } - #endif -  - #ifdef PIKE_DEBUG -  /* For profiling */ -  exit_lex(); - #endif -  -  exit(num); - } -  -  - void low_init_main(void) - { -  void init_builtin(void); -  void init_iterators(void); -  -  init_backend(); -  init_iterators(); -  init_pike_searching(); -  init_error(); -  init_pike_security(); -  th_init(); -  init_operators(); -  -  init_builtin(); -  -  init_builtin_efuns(); -  init_signals(); -  init_dynamic_load(); - } -  - void exit_main(void) - { - #ifdef DO_PIKE_CLEANUP -  cleanup_objects(); - #endif - } -  - void init_main(void) - { - } -  - void low_exit_main(void) - { - #ifdef DO_PIKE_CLEANUP -  void cleanup_added_efuns(void); -  void cleanup_pike_types(void); -  void cleanup_program(void); -  void cleanup_compiler(void); -  void free_all_mapping_blocks(void); -  void free_all_object_blocks(void); -  void free_all_program_blocks(void); -  void exit_builtin(void); -  void exit_iterators(void); -  void exit_backend(void); -  void cleanup_pike_type_table(void); -  void destruct_objects_to_destruct_cb(void); -  - #ifdef AUTO_BIGNUM -  void exit_auto_bignum(void); -  exit_auto_bignum(); - #endif -  -  exit_pike_searching(); -  th_cleanup(); -  exit_object(); -  exit_dynamic_load(); -  exit_signals(); -  exit_builtin(); -  exit_cpp(); -  cleanup_interpret(); -  cleanup_added_efuns(); -  exit_operators(); -  exit_iterators(); -  cleanup_program(); -  cleanup_compiler(); -  cleanup_error(); -  exit_backend(); -  - #ifdef SHARED_NODES -  free(node_hash.table); - #endif /* SHARED_NODES */ -  -  exit_pike_security(); -  free_svalue(& throw_value); -  throw_value.type=T_INT; -  { -  while(1) { -  int tmp=num_objects; -  do_gc(); -  if(num_objects >= tmp) break; -  } -  } -  -  cleanup_gc(); -  -  cleanup_pike_types(); -  - #if defined(PIKE_DEBUG) && defined(DEBUG_MALLOC) -  if(verbose_debug_exit) -  { -  INT32 num,size,recount=0; -  fprintf(stderr,"Exited normally, counting bytes.\n"); -  - #ifdef _REENTRANT -  if(count_pike_threads()>1) -  { -  fprintf(stderr,"Byte counting aborted, because all threads have not exited properly.\n"); -  verbose_debug_exit=0; -  return; -  } - #endif -  -  -  search_all_memheaders_for_references(); -  -  count_memory_in_arrays(&num, &size); -  if(num) -  { -  recount++; -  fprintf(stderr,"Arrays left: %d (%d bytes) (zapped)\n",num,size); -  } -  -  zap_all_arrays(); -  -  count_memory_in_mappings(&num, &size); -  if(num) -  { -  recount++; -  fprintf(stderr,"Mappings left: %d (%d bytes) (zapped)\n",num,size); -  } -  -  zap_all_mappings(); -  -  count_memory_in_multisets(&num, &size); -  if(num) -  fprintf(stderr,"Multisets left: %d (%d bytes)\n",num,size); -  -  -  destruct_objects_to_destruct_cb(); -  if(recount) -  { -  -  fprintf(stderr,"Garbage collecting..\n"); -  do_gc(); -  -  count_memory_in_arrays(&num, &size); -  fprintf(stderr,"Arrays left: %d (%d bytes)\n",num,size); -  count_memory_in_mappings(&num, &size); -  fprintf(stderr,"Mappings left: %d (%d bytes)\n",num,size); -  count_memory_in_multisets(&num, &size); -  fprintf(stderr,"Multisets left: %d (%d bytes)\n",num,size); -  } -  -  -  count_memory_in_programs(&num, &size); -  if(num) -  fprintf(stderr,"Programs left: %d (%d bytes)\n",num,size); -  -  { -  struct program *p; -  for(p=first_program;p;p=p->next) -  describe_something(p, T_PROGRAM, 0,2,0, NULL); -  } -  -  -  count_memory_in_objects(&num, &size); -  if(num) -  fprintf(stderr,"Objects left: %d (%d bytes)\n",num,size); -  -  { -  struct object *o; -  for(o=first_object;o;o=o->next) -  describe_something(o, T_OBJECT, 0,2,0, NULL); -  } -  - #ifdef USE_PIKE_TYPE -  count_memory_in_pike_types(&num, &size); -  if (num) -  fprintf(stderr, "Types left: %d (%d bytes)\n", num, size); -  describe_all_types(); - #endif /* USE_PIKE_TYPE */ -  } - #else -  -  zap_all_arrays(); -  zap_all_mappings(); -  -  destruct_objects_to_destruct_cb(); - #endif -  -  really_clean_up_interpret(); -  -  cleanup_callbacks(); -  free_all_callable_blocks(); -  exit_destroy_called_mark_hash(); -  -  cleanup_pike_type_table(); -  cleanup_shared_string_table(); -  -  free_dynamic_load(); -  first_mapping=0; -  free_all_mapping_blocks(); -  first_object=0; -  free_all_object_blocks(); -  first_program=0; -  free_all_program_blocks(); -  exit_rbtree(); - #endif - } -  -  +