Exemple #1
0
void setupSys() {
    sys_modules_dict = new BoxedDict();
    constants.push_back(sys_modules_dict);

    // This is ok to call here because we've already created the sys_modules_dict
    sys_module = createModule(autoDecref(boxString("sys")));

    // sys_module is what holds on to all of the other modules:
    Py_INCREF(sys_module);
    late_constants.push_back(sys_module);

    sys_module->giveAttrBorrowed("modules", sys_modules_dict);

    BoxedList* sys_path = new BoxedList();
    constants.push_back(sys_path);
    sys_module->giveAttrBorrowed("path", sys_path);

    sys_module->giveAttr("argv", new BoxedList());

    sys_module->giveAttr("exc_info",
                         new BoxedBuiltinFunctionOrMethod(FunctionMetadata::create((void*)sysExcInfo, BOXED_TUPLE, 0),
                                                          "exc_info", exc_info_doc));
    sys_module->giveAttr("exc_clear",
                         new BoxedBuiltinFunctionOrMethod(FunctionMetadata::create((void*)sysExcClear, NONE, 0),
                                                          "exc_clear", exc_clear_doc));
    sys_module->giveAttr(
        "exit", new BoxedBuiltinFunctionOrMethod(FunctionMetadata::create((void*)sysExit, NONE, 1, false, false),
                                                 "exit", { None }, NULL, exit_doc));

    sys_module->giveAttr("warnoptions", new BoxedList());
    sys_module->giveAttrBorrowed("py3kwarning", Py_False);
    sys_module->giveAttr("byteorder", boxString(isLittleEndian() ? "little" : "big"));

    sys_module->giveAttr("platform", boxString(Py_GetPlatform()));

    sys_module->giveAttr("executable", boxString(Py_GetProgramFullPath()));

    sys_module->giveAttr(
        "_getframe",
        new BoxedFunction(FunctionMetadata::create((void*)sysGetFrame, UNKNOWN, 1, false, false), { NULL }));
    sys_module->giveAttr("_current_frames",
                         new BoxedFunction(FunctionMetadata::create((void*)sysCurrentFrames, UNKNOWN, 0)));
    sys_module->giveAttr("getdefaultencoding", new BoxedBuiltinFunctionOrMethod(
                                                   FunctionMetadata::create((void*)sysGetDefaultEncoding, STR, 0),
                                                   "getdefaultencoding", getdefaultencoding_doc));

    sys_module->giveAttr("getfilesystemencoding", new BoxedBuiltinFunctionOrMethod(
                                                      FunctionMetadata::create((void*)sysGetFilesystemEncoding, STR, 0),
                                                      "getfilesystemencoding", getfilesystemencoding_doc));

    sys_module->giveAttr("getrecursionlimit", new BoxedBuiltinFunctionOrMethod(
                                                  FunctionMetadata::create((void*)sysGetRecursionLimit, UNKNOWN, 0),
                                                  "getrecursionlimit", getrecursionlimit_doc));

    // As we don't support compile() etc yet force 'dont_write_bytecode' to true.
    sys_module->giveAttrBorrowed("dont_write_bytecode", Py_True);

    sys_module->giveAttr("prefix", boxString(Py_GetPrefix()));
    sys_module->giveAttr("exec_prefix", boxString(Py_GetExecPrefix()));

    sys_module->giveAttr("copyright",
                         boxString("Copyright 2014-2016 Dropbox.\nAll Rights Reserved.\n\nCopyright (c) 2001-2014 "
                                   "Python Software Foundation.\nAll Rights Reserved.\n\nCopyright (c) 2000 "
                                   "BeOpen.com.\nAll Rights Reserved.\n\nCopyright (c) 1995-2001 Corporation for "
                                   "National Research Initiatives.\nAll Rights Reserved.\n\nCopyright (c) "
                                   "1991-1995 Stichting Mathematisch Centrum, Amsterdam.\nAll Rights Reserved."));

    sys_module->giveAttr("version", boxString(generateVersionString()));
    sys_module->giveAttr("hexversion", boxInt(PY_VERSION_HEX));
    sys_module->giveAttr("subversion", BoxedTuple::create({ autoDecref(boxString("Pyston")), autoDecref(boxString("")),
                                                            autoDecref(boxString("")) }));
    sys_module->giveAttr("maxint", boxInt(PYSTON_INT_MAX));
    sys_module->giveAttr("maxsize", boxInt(PY_SSIZE_T_MAX));

    sys_flags_cls = BoxedClass::create(type_cls, object_cls, 0, 0, sizeof(BoxedSysFlags), false, "flags", false, NULL,
                                       NULL, false);
    sys_flags_cls->giveAttr(
        "__new__", new BoxedFunction(FunctionMetadata::create((void*)BoxedSysFlags::__new__, UNKNOWN, 1, true, true)));
    sys_flags_cls->tp_dealloc = (destructor)BoxedSysFlags::dealloc;
#define ADD(name) sys_flags_cls->giveAttrMember(STRINGIFY(name), T_OBJECT, offsetof(BoxedSysFlags, name));
    ADD(division_warning);
    ADD(bytes_warning);
    ADD(no_user_site);
    ADD(optimize);
#undef ADD

#define SET_SYS_FROM_STRING(key, value) sys_module->giveAttr((key), (value))
#ifdef Py_USING_UNICODE
    SET_SYS_FROM_STRING("maxunicode", PyInt_FromLong(PyUnicode_GetMax()));
#endif

/* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */
#ifndef PY_NO_SHORT_FLOAT_REPR
    SET_SYS_FROM_STRING("float_repr_style", PyString_FromString("short"));
#else
    SET_SYS_FROM_STRING("float_repr_style", PyString_FromString("legacy"));
#endif

    sys_flags_cls->freeze();

    auto sys_str = getStaticString("sys");
    for (auto& md : sys_methods) {
        sys_module->giveAttr(md.ml_name, new BoxedCApiFunction(&md, NULL, sys_str));
    }

    sys_module->giveAttrBorrowed("__displayhook__", sys_module->getattr(autoDecref(internStringMortal("displayhook"))));
    sys_module->giveAttr("flags", new BoxedSysFlags());
}
Exemple #2
0
/*
 * Class:     org_jpy_PyLib
 * Method:    startPython0
 * Signature: ([Ljava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_org_jpy_PyLib_startPython0
  (JNIEnv* jenv, jclass jLibClass, jobjectArray jPathArray)
{
    int pyInit = Py_IsInitialized();

    JPy_DIAG_PRINT(JPy_DIAG_F_ALL, "PyLib_startPython: entered: jenv=%p, pyInit=%d, JPy_Module=%p\n", jenv, pyInit, JPy_Module);

    if (!pyInit) {
        Py_Initialize();
        PyLib_RedirectStdOut();
        pyInit = Py_IsInitialized();
    }

    if (pyInit) {

        if (JPy_DiagFlags != 0) {
            printf("PyLib_startPython: global Python interpreter information:\n");
            #if defined(JPY_COMPAT_33P)
            printf("  Py_GetProgramName()     = \"%ls\"\n", Py_GetProgramName());
            printf("  Py_GetPrefix()          = \"%ls\"\n", Py_GetPrefix());
            printf("  Py_GetExecPrefix()      = \"%ls\"\n", Py_GetExecPrefix());
            printf("  Py_GetProgramFullPath() = \"%ls\"\n", Py_GetProgramFullPath());
            printf("  Py_GetPath()            = \"%ls\"\n", Py_GetPath());
            printf("  Py_GetPythonHome()      = \"%ls\"\n", Py_GetPythonHome());
            #elif defined(JPY_COMPAT_27)
            printf("  Py_GetProgramName()     = \"%s\"\n", Py_GetProgramName());
            printf("  Py_GetPrefix()          = \"%s\"\n", Py_GetPrefix());
            printf("  Py_GetExecPrefix()      = \"%s\"\n", Py_GetExecPrefix());
            printf("  Py_GetProgramFullPath() = \"%s\"\n", Py_GetProgramFullPath());
            printf("  Py_GetPath()            = \"%s\"\n", Py_GetPath());
            printf("  Py_GetPythonHome()      = \"%s\"\n", Py_GetPythonHome());
            #endif
            printf("  Py_GetVersion()         = \"%s\"\n", Py_GetVersion());
            printf("  Py_GetPlatform()        = \"%s\"\n", Py_GetPlatform());
            printf("  Py_GetCompiler()        = \"%s\"\n", Py_GetCompiler());
            printf("  Py_GetBuildInfo()       = \"%s\"\n", Py_GetBuildInfo());
        }

        // If we've got jPathArray, add all entries to Python's "sys.path"
        //
        if (jPathArray != NULL) {
            PyObject* pyPathList;
            PyObject* pyPath;
            jstring jPath;
            jsize i, pathCount;

            pathCount = (*jenv)->GetArrayLength(jenv, jPathArray);
            //printf(">> pathCount=%d\n", pathCount);
            if (pathCount > 0) {

                JPy_BEGIN_GIL_STATE

                pyPathList = PySys_GetObject("path");
                //printf(">> pyPathList=%p, len=%ld\n", pyPathList, PyList_Size(pyPathList));
                if (pyPathList != NULL) {
                    Py_INCREF(pyPathList);
                    for (i = pathCount - 1; i >= 0; i--) {
                        jPath = (*jenv)->GetObjectArrayElement(jenv, jPathArray, i);
                        //printf(">> i=%d, jPath=%p\n", i, jPath);
                        if (jPath != NULL) {
                            pyPath = JPy_FromJString(jenv, jPath);
                            //printf(">> i=%d, pyPath=%p\n", i, pyPath);
                            if (pyPath != NULL) {
                                PyList_Insert(pyPathList, 0, pyPath);
                            }
                        }
                    }
                    Py_DECREF(pyPathList);
                }
                //printf(">> pyPathList=%p, len=%ld\n", pyPathList, PyList_Size(pyPathList));
                //printf(">> pyPathList=%p, len=%ld (check)\n", PySys_GetObject("path"), PyList_Size(PySys_GetObject("path")));

                JPy_END_GIL_STATE
            }
        }
Exemple #3
0
std::string PySetup::get_platform()
{
	return Py_GetPlatform();
}
Exemple #4
0
void setupSys() {
    sys_modules_dict = new BoxedDict();
    PyThreadState_GET()->interp->modules = incref(sys_modules_dict);

    constants.push_back(sys_modules_dict);

    // This is ok to call here because we've already created the sys_modules_dict
    sys_module = createModule(autoDecref(boxString("sys")));

    // sys_module is what holds on to all of the other modules:
    Py_INCREF(sys_module);
    late_constants.push_back(sys_module);

    sys_module->giveAttrBorrowed("modules", sys_modules_dict);

    BoxedList* sys_path = new BoxedList();
    constants.push_back(sys_path);
    sys_module->giveAttrBorrowed("path", sys_path);

    sys_module->giveAttr("argv", new BoxedList());

    sys_module->giveAttr("exc_info", new BoxedBuiltinFunctionOrMethod(BoxedCode::create((void*)sysExcInfo, BOXED_TUPLE,
                                                                                        0, "exc_info", exc_info_doc)));
    sys_module->giveAttr("exc_clear", new BoxedBuiltinFunctionOrMethod(
                                          BoxedCode::create((void*)sysExcClear, NONE, 0, "exc_clear", exc_clear_doc)));
    sys_module->giveAttr(
        "exit", new BoxedBuiltinFunctionOrMethod(
                    BoxedCode::create((void*)sysExit, NONE, 1, false, false, "exit", exit_doc), { Py_None }, NULL));

    sys_module->giveAttr("warnoptions", new BoxedList());
    sys_module->giveAttrBorrowed("py3kwarning", Py_False);
    sys_module->giveAttr("byteorder", boxString(isLittleEndian() ? "little" : "big"));

    sys_module->giveAttr("platform", boxString(Py_GetPlatform()));

    sys_module->giveAttr("executable", boxString(Py_GetProgramFullPath()));

    sys_module->giveAttr(
        "_getframe",
        new BoxedFunction(BoxedCode::create((void*)sysGetFrame, UNKNOWN, 1, false, false, "_getframe"), { NULL }));
    sys_module->giveAttr("_current_frames",
                         new BoxedFunction(BoxedCode::create((void*)sysCurrentFrames, UNKNOWN, 0, "_current_frames")));
    sys_module->giveAttr("getdefaultencoding",
                         new BoxedBuiltinFunctionOrMethod(BoxedCode::create(
                             (void*)sysGetDefaultEncoding, STR, 0, "getdefaultencoding", getdefaultencoding_doc)));

    sys_module->giveAttr("getfilesystemencoding", new BoxedBuiltinFunctionOrMethod(BoxedCode::create(
                                                      (void*)sysGetFilesystemEncoding, STR, 0, "getfilesystemencoding",
                                                      getfilesystemencoding_doc)));

    sys_module->giveAttr("getrecursionlimit",
                         new BoxedBuiltinFunctionOrMethod(BoxedCode::create(
                             (void*)sysGetRecursionLimit, UNKNOWN, 0, "getrecursionlimit", getrecursionlimit_doc)));

    sys_module->giveAttr("dont_write_bytecode", boxBool(Py_DontWriteBytecodeFlag));

    sys_module->giveAttr("prefix", boxString(Py_GetPrefix()));
    sys_module->giveAttr("exec_prefix", boxString(Py_GetExecPrefix()));

    sys_module->giveAttr("copyright",
                         boxString("Copyright 2014-2016 Dropbox.\nAll Rights Reserved.\n\nCopyright (c) 2001-2014 "
                                   "Python Software Foundation.\nAll Rights Reserved.\n\nCopyright (c) 2000 "
                                   "BeOpen.com.\nAll Rights Reserved.\n\nCopyright (c) 1995-2001 Corporation for "
                                   "National Research Initiatives.\nAll Rights Reserved.\n\nCopyright (c) "
                                   "1991-1995 Stichting Mathematisch Centrum, Amsterdam.\nAll Rights Reserved."));

    sys_module->giveAttr("version", boxString(generateVersionString()));
    sys_module->giveAttr("hexversion", boxInt(PY_VERSION_HEX));
    sys_module->giveAttr("subversion", BoxedTuple::create({ autoDecref(boxString("Pyston")), autoDecref(boxString("")),
                                                            autoDecref(boxString("")) }));
    sys_module->giveAttr("maxint", boxInt(PYSTON_INT_MAX));
    sys_module->giveAttr("maxsize", boxInt(PY_SSIZE_T_MAX));

#define SET_SYS_FROM_STRING(key, value) sys_module->giveAttr((key), (value))
#ifdef Py_USING_UNICODE
    SET_SYS_FROM_STRING("maxunicode", PyInt_FromLong(PyUnicode_GetMax()));
#endif

/* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */
#ifndef PY_NO_SHORT_FLOAT_REPR
    SET_SYS_FROM_STRING("float_repr_style", PyString_FromString("short"));
#else
    SET_SYS_FROM_STRING("float_repr_style", PyString_FromString("legacy"));
#endif


    auto sys_str = getStaticString("sys");
    for (auto& md : sys_methods) {
        sys_module->giveAttr(md.ml_name, new BoxedCApiFunction(&md, NULL, sys_str));
    }

    sys_module->giveAttrBorrowed("__displayhook__", sys_module->getattr(autoDecref(internStringMortal("displayhook"))));
}
Exemple #5
0
void setupSys() {
    sys_modules_dict = new BoxedDict();
    gc::registerPermanentRoot(sys_modules_dict);

    // This is ok to call here because we've already created the sys_modules_dict
    sys_module = createModule("sys");

    sys_module->giveAttr("modules", sys_modules_dict);

    BoxedList* sys_path = new BoxedList();
    sys_module->giveAttr("path", sys_path);

    sys_module->giveAttr("argv", new BoxedList());

    sys_module->giveAttr("stdout", new BoxedFile(stdout, "<stdout>", "w"));
    sys_module->giveAttr("stdin", new BoxedFile(stdin, "<stdin>", "r"));
    sys_module->giveAttr("stderr", new BoxedFile(stderr, "<stderr>", "w"));
    sys_module->giveAttr("__stdout__", sys_module->getattr(internStringMortal("stdout")));
    sys_module->giveAttr("__stdin__", sys_module->getattr(internStringMortal("stdin")));
    sys_module->giveAttr("__stderr__", sys_module->getattr(internStringMortal("stderr")));

    sys_module->giveAttr(
        "exc_info", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)sysExcInfo, BOXED_TUPLE, 0), "exc_info"));
    sys_module->giveAttr("exc_clear",
                         new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)sysExcClear, NONE, 0), "exc_clear"));
    sys_module->giveAttr("exit", new BoxedBuiltinFunctionOrMethod(
                                     boxRTFunction((void*)sysExit, NONE, 1, 1, false, false), "exit", { None }));

    sys_module->giveAttr("warnoptions", new BoxedList());
    sys_module->giveAttr("py3kwarning", False);
    sys_module->giveAttr("byteorder", boxString(isLittleEndian() ? "little" : "big"));

    sys_module->giveAttr("platform", boxString(Py_GetPlatform()));

    sys_module->giveAttr("executable", boxString(Py_GetProgramFullPath()));

    sys_module->giveAttr("_getframe",
                         new BoxedFunction(boxRTFunction((void*)sysGetFrame, UNKNOWN, 1, 1, false, false), { NULL }));
    sys_module->giveAttr(
        "getdefaultencoding",
        new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)sysGetDefaultEncoding, STR, 0), "getdefaultencoding"));

    sys_module->giveAttr("getfilesystemencoding",
                         new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)sysGetFilesystemEncoding, STR, 0),
                                                          "getfilesystemencoding"));

    sys_module->giveAttr(
        "getrecursionlimit",
        new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)sysGetRecursionLimit, UNKNOWN, 0), "getrecursionlimit"));

    sys_module->giveAttr("meta_path", new BoxedList());
    sys_module->giveAttr("path_hooks", new BoxedList());
    sys_module->giveAttr("path_importer_cache", new BoxedDict());

    // As we don't support compile() etc yet force 'dont_write_bytecode' to true.
    sys_module->giveAttr("dont_write_bytecode", True);

    sys_module->giveAttr("prefix", boxString(Py_GetPrefix()));
    sys_module->giveAttr("exec_prefix", boxString(Py_GetExecPrefix()));

    sys_module->giveAttr("copyright",
                         boxString("Copyright 2014-2015 Dropbox.\nAll Rights Reserved.\n\nCopyright (c) 2001-2014 "
                                   "Python Software Foundation.\nAll Rights Reserved.\n\nCopyright (c) 2000 "
                                   "BeOpen.com.\nAll Rights Reserved.\n\nCopyright (c) 1995-2001 Corporation for "
                                   "National Research Initiatives.\nAll Rights Reserved.\n\nCopyright (c) "
                                   "1991-1995 Stichting Mathematisch Centrum, Amsterdam.\nAll Rights Reserved."));

    sys_module->giveAttr("version", boxString(generateVersionString()));
    sys_module->giveAttr("hexversion", boxInt(PY_VERSION_HEX));
    // TODO: this should be a "sys.version_info" object, not just a tuple (ie can access fields by name)
    sys_module->giveAttr("version_info",
                         BoxedTuple::create({ boxInt(PYTHON_VERSION_MAJOR), boxInt(PYTHON_VERSION_MINOR),
                                              boxInt(PYTHON_VERSION_MICRO), boxString("beta"), boxInt(0) }));

    sys_module->giveAttr("maxint", boxInt(PYSTON_INT_MAX));
    sys_module->giveAttr("maxsize", boxInt(PY_SSIZE_T_MAX));

    sys_flags_cls = new (0) BoxedHeapClass(object_cls, BoxedSysFlags::gcHandler, 0, 0, sizeof(BoxedSysFlags), false,
                                           static_cast<BoxedString*>(boxString("flags")));
    sys_flags_cls->giveAttr("__new__",
                            new BoxedFunction(boxRTFunction((void*)BoxedSysFlags::__new__, UNKNOWN, 1, 0, true, true)));
#define ADD(name)                                                                                                      \
    sys_flags_cls->giveAttr(STRINGIFY(name),                                                                           \
                            new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedSysFlags, name)))
    ADD(division_warning);
    ADD(bytes_warning);
    ADD(no_user_site);
    ADD(optimize);
#undef ADD

#define SET_SYS_FROM_STRING(key, value) sys_module->giveAttr((key), (value))
#ifdef Py_USING_UNICODE
    SET_SYS_FROM_STRING("maxunicode", PyInt_FromLong(PyUnicode_GetMax()));
#endif

    sys_flags_cls->tp_mro = BoxedTuple::create({ sys_flags_cls, object_cls });
    sys_flags_cls->freeze();

    for (auto& md : sys_methods) {
        sys_module->giveAttr(md.ml_name, new BoxedCApiFunction(&md, sys_module));
    }

    sys_module->giveAttr("__displayhook__", sys_module->getattr(internStringMortal("displayhook")));
    sys_module->giveAttr("flags", new BoxedSysFlags());
}
Exemple #6
0
static void smisk_crash_sighandler(int signum, siginfo_t* info, void*ptr) {
  FILE *out = NULL;
  char out_fn[PATH_MAX];
  char cwd_buf[PATH_MAX];
  char *cwd = NULL;
  struct tm *t;
  time_t timer;
  size_t i = 0;
  const char *found_gdb_path;
  char cmd[1024];
  // Signal code table (from http://www.opengroup.org/onlinepubs/007908799/xsh/signal.h.html)
  static const char *si_codes[][9] = {
    {"", "", "", "", "", "", "", "", ""},
    {"", "", "", "", "", "", "", "", ""},
    {"", "", "", "", "", "", "", "", ""},
    {"",
     "ILL_ILLOPC\tillegal opcode",
     "ILL_ILLOPN\tillegal operand",
     "ILL_ILLADR\tillegal addressing mode",
     "ILL_ILLTRP\tillegal trap",
     "ILL_PRVOPC\tprivileged opcode",
     "ILL_PRVREG\tprivileged register",
     "ILL_COPROC\tcoprocessor error",
     "ILL_BADSTK\tinternal stack error"}, // ILL
    {"", "", "", "", "", "", "", "", ""},
    {"", "", "", "", "", "", "", "", ""},
    {"", "", "", "", "", "", "", "", ""},
    {"",
     "FPE_INTDIV\tinteger divide by zero",
     "FPE_INTOVF\tinteger overflow", 
     "FPE_FLTDIV\tfloating point divide by zero",
     "FPE_FLTOVF\tfloating point overflow",
     "FPE_FLTUND\tfloating point underflow",
     "FPE_FLTRES\tfloating point inexact result",
     "FPE_FLTINV\tinvalid floating point operation",
     "FPE_FLTSUB\tsubscript out of range"}, // FPE
    {"", "", "", "", "", "", "", "", ""},
    {"",
     "BUS_ADRALN\tinvalid address alignment",
     "BUS_ADRERR\tnon-existent physical address",
     "BUS_OBJERR\tobject specific hardware error",
     "", "", "", ""}, // BUS
    {"",
     "SEGV_MAPERR\taddress not mapped to object",
     "SEGV_ACCERR\tinvalid permissions for mapped object",
     "", "", "", "", "", ""} // SEGV
  };
  // Possible paths to GDB
  static const char *gdb_path[] = {
    "/usr/bin/gdb",
    "/usr/local/bin/gdb",
    "/opt/local/bin/gdb",
    "/opt/bin/gdb",
    "/local/bin/gdb",
    NULL
  };
  
  // Header
  fputs("FATAL: smisk died from ", stderr);
  switch(signum) {
    case SIGILL:
      fputs("Illegal instruction ", stderr);
      break;
    case SIGFPE:
      fputs("Floating-point exception ", stderr);
      break;
    case SIGBUS:
      fputs("Bus error ", stderr);
      break;
    case SIGSEGV:
      fputs("Segmentation violation ", stderr);
      break;
  }
  fprintf(stderr, "[%d] ", signum);
  fflush(stderr);
  
  // Construct filename smisk-YYYYMMDD-HHMMSS.PID.crash
  timer = time(NULL);
  t = localtime(&timer);
  cwd = getcwd(cwd_buf, PATH_MAX);
  sprintf(out_fn, "%s/smisk-%04d%02d%02d-%02d%02d%02d.%d.crash",
    (access(cwd ? cwd : ".", W_OK) == 0) ? (cwd ? cwd : ".") : "/tmp",
    1900+t->tm_year, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, getpid());
  
  // Open file
  fprintf(stderr, "Writing crash dump to %s...\n", out_fn);
  out = fopen(out_fn, "w");
  if (!out)
    out = stderr;
  
  // Basic info
  fprintf(out, "Time:               %04d-%02d-%02d %02d:%02d:%02d\n",
    1900+t->tm_year, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
  fprintf(out, "Process:            %d\n", getpid());
  fprintf(out, "Working directory:  %s\n", cwd ? cwd : "?");
  fprintf(out, "Python:             %s %s\n", Py_GetProgramFullPath(), Py_GetVersion());
  fprintf(out, "Smisk:              %s (%s)\n", SMISK_VERSION, SMISK_BUILD_ID);
  #if HAVE_SYS_UTSNAME_H
    struct utsname un;
    if (uname(&un) == 0) {
      fprintf(out, "System:             %s, %s, %s, %s\n",
        un.sysname, un.release, un.version, un.machine);
      fprintf(out, "Hostname:           %s\n", un.nodename);
    }
    else
  #endif
    fprintf(out, "System:             %s\n", Py_GetPlatform());
  fprintf(out, "\n");
  fprintf(out, "Signal:             %d\n", signum);
  fprintf(out, "Errno:              %d\n", info->si_errno);
  fprintf(out, "Code:               %d\t%s\n", info->si_code, (signum > 0) ? si_codes[signum-1][info->si_code] : "?");
  fprintf(out, "Address:            %p\n", info->si_addr);
  
  // Find GDB
  i = 0;
  found_gdb_path = NULL;
  do {
    if (access(*(gdb_path+i), R_OK) == 0) {
      found_gdb_path = *(gdb_path+i);
      log_debug("found gdb at %s", found_gdb_path);
      break;
    }
  } while ( *(gdb_path + ++i) );
  
  // Write backtrace
  fprintf(out, "\nBacktrace:\n");
  if (found_gdb_path) {
    fclose(out);
    system("/bin/echo 'backtrace' > /tmp/smisk_gdb_args");
    sprintf(cmd, "%s -batch -x /tmp/smisk_gdb_args %s %d >> %s",
      found_gdb_path, Py_GetProgramFullPath(), getpid(), out_fn);
    system(cmd);
  }
  else {
    log_error("Note: GDB not found. Install GDB to get a more detailed backtrace.");
    smisk_crash_write_backtrace(info, ptr, out);
    fclose(out);
  }
  
  //exit(-1);
  _exit(-1);
}