To: vim_dev@googlegroups.com Subject: Patch 7.3.1287 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.3.1287 Problem: Python SystemExit exception is not handled properly. Solution: Catch the exception and give an error. (Yasuhiro Matsumoto, Ken Takata) Files: runtime/doc/if_pyth.txt, src/if_py_both.h, src/if_python.c, src/if_python3.c *** ../vim-7.3.1286/runtime/doc/if_pyth.txt 2013-06-12 14:40:58.000000000 +0200 --- runtime/doc/if_pyth.txt 2013-07-01 21:56:02.000000000 +0200 *************** *** 740,745 **** --- 740,750 ---- 3. You undefine PY_NO_RTLD_GLOBAL in auto/config.h after configuration. This may crash Vim though. + *E880* + Raising SystemExit exception in python isn't endorsed way to quit vim, use: > + :py vim.command("qall!") + < + *has-python* You can test what Python version is available with: > if has('python') *** ../vim-7.3.1286/src/if_py_both.h 2013-06-24 22:33:26.000000000 +0200 --- src/if_py_both.h 2013-07-01 22:02:17.000000000 +0200 *************** *** 13,18 **** --- 13,20 ---- * Common code for if_python.c and if_python3.c. */ + static char_u e_py_systemexit[] = "E880: Can't handle SystemExit of %s exception in vim"; + #if PY_VERSION_HEX < 0x02050000 typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */ #endif *************** *** 275,281 **** if (self) for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method) ! if (add_string(ret, (char *) method->ml_name)) { Py_DECREF(ret); return NULL; --- 277,283 ---- if (self) for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method) ! if (add_string(ret, (char *)method->ml_name)) { Py_DECREF(ret); return NULL; *************** *** 549,556 **** VimTryEnd(void) { --trylevel; ! /* Without this it stops processing all subsequent VimL commands and ! * generates strange error messages if I e.g. try calling Test() in a cycle */ did_emsg = FALSE; /* Keyboard interrupt should be preferred over anything else */ if (got_int) --- 551,559 ---- VimTryEnd(void) { --trylevel; ! /* Without this it stops processing all subsequent VimL commands and ! * generates strange error messages if I e.g. try calling Test() in a ! * cycle */ did_emsg = FALSE; /* Keyboard interrupt should be preferred over anything else */ if (got_int) *************** *** 570,576 **** /* Finally transform VimL exception to python one */ else { ! PyErr_SetVim((char *) current_exception->value); discard_current_exception(); return -1; } --- 573,579 ---- /* Finally transform VimL exception to python one */ else { ! PyErr_SetVim((char *)current_exception->value); discard_current_exception(); return -1; } *************** *** 667,673 **** /* For backwards compatibility numbers are stored as strings. */ sprintf(buf, "%ld", (long)our_tv->vval.v_number); ! ret = PyString_FromString((char *) buf); } # ifdef FEAT_FLOAT else if (our_tv->v_type == VAR_FLOAT) --- 670,676 ---- /* For backwards compatibility numbers are stored as strings. */ sprintf(buf, "%ld", (long)our_tv->vval.v_number); ! ret = PyString_FromString((char *)buf); } # ifdef FEAT_FLOAT else if (our_tv->v_type == VAR_FLOAT) *************** *** 675,681 **** char buf[NUMBUFLEN]; sprintf(buf, "%f", our_tv->vval.v_float); ! ret = PyString_FromString((char *) buf); } # endif else if (our_tv->v_type == VAR_LIST) --- 678,684 ---- char buf[NUMBUFLEN]; sprintf(buf, "%f", our_tv->vval.v_float); ! ret = PyString_FromString((char *)buf); } # endif else if (our_tv->v_type == VAR_LIST) *************** *** 955,961 **** PyObject *pathObject; map_rtp_data *mr_data = *((map_rtp_data **) data); ! if (!(pathObject = PyString_FromString((char *) path))) { *data = NULL; return; --- 958,964 ---- PyObject *pathObject; map_rtp_data *mr_data = *((map_rtp_data **) data); ! if (!(pathObject = PyString_FromString((char *)path))) { *data = NULL; return; *************** *** 1124,1130 **** PyObject *module; char *dot; ! if ((dot = (char *) vim_strchr((char_u *) tail, '.'))) { /* * There is a dot in the name: call find_module recursively without the --- 1127,1133 ---- PyObject *module; char *dot; ! if ((dot = (char *)vim_strchr((char_u *) tail, '.'))) { /* * There is a dot in the name: call find_module recursively without the *************** *** 1658,1664 **** --((*dii)->todo); ! if (!(ret = PyBytes_FromString((char *) (*dii)->hi->hi_key))) return NULL; return ret; --- 1661,1667 ---- --((*dii)->todo); ! if (!(ret = PyBytes_FromString((char *)(*dii)->hi->hi_key))) return NULL; return ret; *************** *** 2680,2691 **** FunctionRepr(FunctionObject *self) { #ifdef Py_TRACE_REFS ! /* For unknown reason self->name may be NULL after calling * Finalize */ return PyString_FromFormat("", ! (self->name == NULL ? "" : (char *) self->name)); #else ! return PyString_FromFormat("", (char *) self->name); #endif } --- 2683,2694 ---- FunctionRepr(FunctionObject *self) { #ifdef Py_TRACE_REFS ! /* For unknown reason self->name may be NULL after calling * Finalize */ return PyString_FromFormat("", ! (self->name == NULL ? "" : (char *)self->name)); #else ! return PyString_FromFormat("", (char *)self->name); #endif } *************** *** 2809,2815 **** { if (stringval) { ! PyObject *ret = PyBytes_FromString((char *) stringval); vim_free(stringval); return ret; } --- 2812,2818 ---- { if (stringval) { ! PyObject *ret = PyBytes_FromString((char *)stringval); vim_free(stringval); return ret; } *************** *** 4525,4531 **** { if (strcmp(name, "name") == 0) return PyString_FromString((self->buf->b_ffname == NULL ! ? "" : (char *) self->buf->b_ffname)); else if (strcmp(name, "number") == 0) return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum); else if (strcmp(name, "vars") == 0) --- 4528,4534 ---- { if (strcmp(name, "name") == 0) return PyString_FromString((self->buf->b_ffname == NULL ! ? "" : (char *)self->buf->b_ffname)); else if (strcmp(name, "number") == 0) return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum); else if (strcmp(name, "vars") == 0) *************** *** 4961,4967 **** #endif ) { ! PyRun_SimpleString((char *) cmd); } static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n "; --- 4964,4982 ---- #endif ) { ! PyObject *run_ret; ! run_ret = PyRun_String((char *)cmd, Py_file_input, globals, globals); ! if (run_ret != NULL) ! { ! Py_DECREF(run_ret); ! } ! else if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit)) ! { ! EMSG2(_(e_py_systemexit), "python"); ! PyErr_Clear(); ! } ! else ! PyErr_PrintEx(1); } static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n "; *************** *** 4979,4984 **** --- 4994,5000 ---- char *code; int status; PyObject *pyfunc, *pymain; + PyObject *run_ret; if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK) { *************** *** 4990,4996 **** code = PyMem_New(char, len + 1); memcpy(code, code_hdr, code_hdr_len); STRCPY(code + code_hdr_len, cmd); ! status = PyRun_SimpleString(code); PyMem_Free(code); if (status) --- 5006,5028 ---- code = PyMem_New(char, len + 1); memcpy(code, code_hdr, code_hdr_len); STRCPY(code + code_hdr_len, cmd); ! run_ret = PyRun_String(code, Py_file_input, globals, globals); ! status = -1; ! if (run_ret != NULL) ! { ! status = 0; ! Py_DECREF(run_ret); ! } ! else if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit)) ! { ! PyMem_Free(code); ! EMSG2(_(e_py_systemexit), "python"); ! PyErr_Clear(); ! return; ! } ! else ! PyErr_PrintEx(1); ! PyMem_Free(code); if (status) *************** *** 5068,5076 **** { PyObject *run_ret; ! run_ret = PyRun_String((char *) cmd, Py_eval_input, globals, globals); if (run_ret == NULL) { if (PyErr_Occurred() && !msg_silent) PyErr_PrintEx(0); EMSG(_("E858: Eval did not return a valid python object")); --- 5100,5113 ---- { PyObject *run_ret; ! run_ret = PyRun_String((char *)cmd, Py_eval_input, globals, globals); if (run_ret == NULL) { + if (PyErr_ExceptionMatches(PyExc_SystemExit)) + { + EMSG2(_(e_py_systemexit), "python"); + PyErr_Clear(); + } if (PyErr_Occurred() && !msg_silent) PyErr_PrintEx(0); EMSG(_("E858: Eval did not return a valid python object")); *** ../vim-7.3.1286/src/if_python.c 2013-06-24 20:32:54.000000000 +0200 --- src/if_python.c 2013-07-01 21:56:02.000000000 +0200 *************** *** 444,449 **** --- 444,450 ---- static PyObject *imp_PyExc_KeyboardInterrupt; static PyObject *imp_PyExc_TypeError; static PyObject *imp_PyExc_ValueError; + static PyObject *imp_PyExc_SystemExit; static PyObject *imp_PyExc_RuntimeError; static PyObject *imp_PyExc_ImportError; static PyObject *imp_PyExc_OverflowError; *************** *** 454,459 **** --- 455,461 ---- # define PyExc_KeyboardInterrupt imp_PyExc_KeyboardInterrupt # define PyExc_TypeError imp_PyExc_TypeError # define PyExc_ValueError imp_PyExc_ValueError + # define PyExc_SystemExit imp_PyExc_SystemExit # define PyExc_RuntimeError imp_PyExc_RuntimeError # define PyExc_ImportError imp_PyExc_ImportError # define PyExc_OverflowError imp_PyExc_OverflowError *************** *** 731,736 **** --- 733,739 ---- imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt"); imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError"); imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError"); + imp_PyExc_SystemExit = PyDict_GetItemString(exdict, "SystemExit"); imp_PyExc_RuntimeError = PyDict_GetItemString(exdict, "RuntimeError"); imp_PyExc_ImportError = PyDict_GetItemString(exdict, "ImportError"); imp_PyExc_OverflowError = PyDict_GetItemString(exdict, "OverflowError"); *************** *** 740,745 **** --- 743,749 ---- Py_XINCREF(imp_PyExc_KeyboardInterrupt); Py_XINCREF(imp_PyExc_TypeError); Py_XINCREF(imp_PyExc_ValueError); + Py_XINCREF(imp_PyExc_SystemExit); Py_XINCREF(imp_PyExc_RuntimeError); Py_XINCREF(imp_PyExc_ImportError); Py_XINCREF(imp_PyExc_OverflowError); *** ../vim-7.3.1286/src/if_python3.c 2013-06-23 16:35:32.000000000 +0200 --- src/if_python3.c 2013-07-01 21:56:02.000000000 +0200 *************** *** 126,132 **** # define PyErr_PrintEx py3_PyErr_PrintEx # define PyErr_NoMemory py3_PyErr_NoMemory # define PyErr_Occurred py3_PyErr_Occurred - # define PyErr_PrintEx py3_PyErr_PrintEx # define PyErr_SetNone py3_PyErr_SetNone # define PyErr_SetString py3_PyErr_SetString # define PyErr_SetObject py3_PyErr_SetObject --- 126,131 ---- *************** *** 403,408 **** --- 402,408 ---- static PyObject *p3imp_PyExc_KeyboardInterrupt; static PyObject *p3imp_PyExc_TypeError; static PyObject *p3imp_PyExc_ValueError; + static PyObject *p3imp_PyExc_SystemExit; static PyObject *p3imp_PyExc_RuntimeError; static PyObject *p3imp_PyExc_ImportError; static PyObject *p3imp_PyExc_OverflowError; *************** *** 413,418 **** --- 413,419 ---- # define PyExc_KeyboardInterrupt p3imp_PyExc_KeyboardInterrupt # define PyExc_TypeError p3imp_PyExc_TypeError # define PyExc_ValueError p3imp_PyExc_ValueError + # define PyExc_SystemExit p3imp_PyExc_SystemExit # define PyExc_RuntimeError p3imp_PyExc_RuntimeError # define PyExc_ImportError p3imp_PyExc_ImportError # define PyExc_OverflowError p3imp_PyExc_OverflowError *************** *** 681,686 **** --- 682,688 ---- p3imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt"); p3imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError"); p3imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError"); + p3imp_PyExc_SystemExit = PyDict_GetItemString(exdict, "SystemExit"); p3imp_PyExc_RuntimeError = PyDict_GetItemString(exdict, "RuntimeError"); p3imp_PyExc_ImportError = PyDict_GetItemString(exdict, "ImportError"); p3imp_PyExc_OverflowError = PyDict_GetItemString(exdict, "OverflowError"); *************** *** 690,695 **** --- 692,698 ---- Py_XINCREF(p3imp_PyExc_KeyboardInterrupt); Py_XINCREF(p3imp_PyExc_TypeError); Py_XINCREF(p3imp_PyExc_ValueError); + Py_XINCREF(p3imp_PyExc_SystemExit); Py_XINCREF(p3imp_PyExc_RuntimeError); Py_XINCREF(p3imp_PyExc_ImportError); Py_XINCREF(p3imp_PyExc_OverflowError); *** ../vim-7.3.1286/src/version.c 2013-07-01 21:43:05.000000000 +0200 --- src/version.c 2013-07-01 21:57:00.000000000 +0200 *************** *** 730,731 **** --- 730,733 ---- { /* Add new patch number below this line */ + /**/ + 1287, /**/ -- 5 out of 4 people have trouble with fractions. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///