1
0
forked from aniani/vim

updated for version 7.3.1287

Problem:    Python SystemExit exception is not handled properly.
Solution:   Catch the exception and give an error. (Yasuhiro Matsumoto, Ken
            Takata)
This commit is contained in:
Bram Moolenaar
2013-07-01 22:03:04 +02:00
parent c33916a6e0
commit 4100937474
5 changed files with 69 additions and 18 deletions

View File

@@ -740,6 +740,11 @@ To work around such problems there are these options:
3. You undefine PY_NO_RTLD_GLOBAL in auto/config.h after configuration. This 3. You undefine PY_NO_RTLD_GLOBAL in auto/config.h after configuration. This
may crash Vim though. may crash Vim though.
*E880*
Raising SystemExit exception in python isn't endorsed way to quit vim, use: >
:py vim.command("qall!")
<
*has-python* *has-python*
You can test what Python version is available with: > You can test what Python version is available with: >
if has('python') if has('python')

View File

@@ -13,6 +13,8 @@
* Common code for if_python.c and if_python3.c. * 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 #if PY_VERSION_HEX < 0x02050000
typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */ typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */
#endif #endif
@@ -275,7 +277,7 @@ ObjectDir(PyObject *self, char **attributes)
if (self) if (self)
for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method) for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method)
if (add_string(ret, (char *) method->ml_name)) if (add_string(ret, (char *)method->ml_name))
{ {
Py_DECREF(ret); Py_DECREF(ret);
return NULL; return NULL;
@@ -550,7 +552,8 @@ VimTryEnd(void)
{ {
--trylevel; --trylevel;
/* Without this it stops processing all subsequent VimL commands and /* Without this it stops processing all subsequent VimL commands and
* generates strange error messages if I e.g. try calling Test() in a cycle */ * generates strange error messages if I e.g. try calling Test() in a
* cycle */
did_emsg = FALSE; did_emsg = FALSE;
/* Keyboard interrupt should be preferred over anything else */ /* Keyboard interrupt should be preferred over anything else */
if (got_int) if (got_int)
@@ -570,7 +573,7 @@ VimTryEnd(void)
/* Finally transform VimL exception to python one */ /* Finally transform VimL exception to python one */
else else
{ {
PyErr_SetVim((char *) current_exception->value); PyErr_SetVim((char *)current_exception->value);
discard_current_exception(); discard_current_exception();
return -1; return -1;
} }
@@ -667,7 +670,7 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
/* For backwards compatibility numbers are stored as strings. */ /* For backwards compatibility numbers are stored as strings. */
sprintf(buf, "%ld", (long)our_tv->vval.v_number); sprintf(buf, "%ld", (long)our_tv->vval.v_number);
ret = PyString_FromString((char *) buf); ret = PyString_FromString((char *)buf);
} }
# ifdef FEAT_FLOAT # ifdef FEAT_FLOAT
else if (our_tv->v_type == VAR_FLOAT) else if (our_tv->v_type == VAR_FLOAT)
@@ -675,7 +678,7 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
char buf[NUMBUFLEN]; char buf[NUMBUFLEN];
sprintf(buf, "%f", our_tv->vval.v_float); sprintf(buf, "%f", our_tv->vval.v_float);
ret = PyString_FromString((char *) buf); ret = PyString_FromString((char *)buf);
} }
# endif # endif
else if (our_tv->v_type == VAR_LIST) else if (our_tv->v_type == VAR_LIST)
@@ -955,7 +958,7 @@ map_rtp_callback(char_u *path, void *_data)
PyObject *pathObject; PyObject *pathObject;
map_rtp_data *mr_data = *((map_rtp_data **) data); map_rtp_data *mr_data = *((map_rtp_data **) data);
if (!(pathObject = PyString_FromString((char *) path))) if (!(pathObject = PyString_FromString((char *)path)))
{ {
*data = NULL; *data = NULL;
return; return;
@@ -1124,7 +1127,7 @@ find_module(char *fullname, char *tail, PyObject *new_path)
PyObject *module; PyObject *module;
char *dot; char *dot;
if ((dot = (char *) vim_strchr((char_u *) tail, '.'))) if ((dot = (char *)vim_strchr((char_u *) tail, '.')))
{ {
/* /*
* There is a dot in the name: call find_module recursively without the * There is a dot in the name: call find_module recursively without the
@@ -1658,7 +1661,7 @@ DictionaryIterNext(dictiterinfo_T **dii)
--((*dii)->todo); --((*dii)->todo);
if (!(ret = PyBytes_FromString((char *) (*dii)->hi->hi_key))) if (!(ret = PyBytes_FromString((char *)(*dii)->hi->hi_key)))
return NULL; return NULL;
return ret; return ret;
@@ -2683,9 +2686,9 @@ FunctionRepr(FunctionObject *self)
/* For unknown reason self->name may be NULL after calling /* For unknown reason self->name may be NULL after calling
* Finalize */ * Finalize */
return PyString_FromFormat("<vim.Function '%s'>", return PyString_FromFormat("<vim.Function '%s'>",
(self->name == NULL ? "<NULL>" : (char *) self->name)); (self->name == NULL ? "<NULL>" : (char *)self->name));
#else #else
return PyString_FromFormat("<vim.Function '%s'>", (char *) self->name); return PyString_FromFormat("<vim.Function '%s'>", (char *)self->name);
#endif #endif
} }
@@ -2809,7 +2812,7 @@ OptionsItem(OptionsObject *self, PyObject *keyObject)
{ {
if (stringval) if (stringval)
{ {
PyObject *ret = PyBytes_FromString((char *) stringval); PyObject *ret = PyBytes_FromString((char *)stringval);
vim_free(stringval); vim_free(stringval);
return ret; return ret;
} }
@@ -4525,7 +4528,7 @@ BufferAttr(BufferObject *self, char *name)
{ {
if (strcmp(name, "name") == 0) if (strcmp(name, "name") == 0)
return PyString_FromString((self->buf->b_ffname == NULL return PyString_FromString((self->buf->b_ffname == NULL
? "" : (char *) self->buf->b_ffname)); ? "" : (char *)self->buf->b_ffname));
else if (strcmp(name, "number") == 0) else if (strcmp(name, "number") == 0)
return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum); return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
else if (strcmp(name, "vars") == 0) else if (strcmp(name, "vars") == 0)
@@ -4961,7 +4964,19 @@ run_cmd(const char *cmd, void *arg UNUSED
#endif #endif
) )
{ {
PyRun_SimpleString((char *) cmd); 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 "; static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
@@ -4979,6 +4994,7 @@ run_do(const char *cmd, void *arg UNUSED
char *code; char *code;
int status; int status;
PyObject *pyfunc, *pymain; PyObject *pyfunc, *pymain;
PyObject *run_ret;
if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK) if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK)
{ {
@@ -4990,7 +5006,23 @@ run_do(const char *cmd, void *arg UNUSED
code = PyMem_New(char, len + 1); code = PyMem_New(char, len + 1);
memcpy(code, code_hdr, code_hdr_len); memcpy(code, code_hdr, code_hdr_len);
STRCPY(code + code_hdr_len, cmd); STRCPY(code + code_hdr_len, cmd);
status = PyRun_SimpleString(code); 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); PyMem_Free(code);
if (status) if (status)
@@ -5068,9 +5100,14 @@ run_eval(const char *cmd, typval_T *rettv
{ {
PyObject *run_ret; PyObject *run_ret;
run_ret = PyRun_String((char *) cmd, Py_eval_input, globals, globals); run_ret = PyRun_String((char *)cmd, Py_eval_input, globals, globals);
if (run_ret == NULL) if (run_ret == NULL)
{ {
if (PyErr_ExceptionMatches(PyExc_SystemExit))
{
EMSG2(_(e_py_systemexit), "python");
PyErr_Clear();
}
if (PyErr_Occurred() && !msg_silent) if (PyErr_Occurred() && !msg_silent)
PyErr_PrintEx(0); PyErr_PrintEx(0);
EMSG(_("E858: Eval did not return a valid python object")); EMSG(_("E858: Eval did not return a valid python object"));

View File

@@ -444,6 +444,7 @@ static PyObject *imp_PyExc_KeyError;
static PyObject *imp_PyExc_KeyboardInterrupt; static PyObject *imp_PyExc_KeyboardInterrupt;
static PyObject *imp_PyExc_TypeError; static PyObject *imp_PyExc_TypeError;
static PyObject *imp_PyExc_ValueError; static PyObject *imp_PyExc_ValueError;
static PyObject *imp_PyExc_SystemExit;
static PyObject *imp_PyExc_RuntimeError; static PyObject *imp_PyExc_RuntimeError;
static PyObject *imp_PyExc_ImportError; static PyObject *imp_PyExc_ImportError;
static PyObject *imp_PyExc_OverflowError; static PyObject *imp_PyExc_OverflowError;
@@ -454,6 +455,7 @@ static PyObject *imp_PyExc_OverflowError;
# define PyExc_KeyboardInterrupt imp_PyExc_KeyboardInterrupt # define PyExc_KeyboardInterrupt imp_PyExc_KeyboardInterrupt
# define PyExc_TypeError imp_PyExc_TypeError # define PyExc_TypeError imp_PyExc_TypeError
# define PyExc_ValueError imp_PyExc_ValueError # define PyExc_ValueError imp_PyExc_ValueError
# define PyExc_SystemExit imp_PyExc_SystemExit
# define PyExc_RuntimeError imp_PyExc_RuntimeError # define PyExc_RuntimeError imp_PyExc_RuntimeError
# define PyExc_ImportError imp_PyExc_ImportError # define PyExc_ImportError imp_PyExc_ImportError
# define PyExc_OverflowError imp_PyExc_OverflowError # define PyExc_OverflowError imp_PyExc_OverflowError
@@ -731,6 +733,7 @@ get_exceptions(void)
imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt"); imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt");
imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError"); imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError");
imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError"); imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError");
imp_PyExc_SystemExit = PyDict_GetItemString(exdict, "SystemExit");
imp_PyExc_RuntimeError = PyDict_GetItemString(exdict, "RuntimeError"); imp_PyExc_RuntimeError = PyDict_GetItemString(exdict, "RuntimeError");
imp_PyExc_ImportError = PyDict_GetItemString(exdict, "ImportError"); imp_PyExc_ImportError = PyDict_GetItemString(exdict, "ImportError");
imp_PyExc_OverflowError = PyDict_GetItemString(exdict, "OverflowError"); imp_PyExc_OverflowError = PyDict_GetItemString(exdict, "OverflowError");
@@ -740,6 +743,7 @@ get_exceptions(void)
Py_XINCREF(imp_PyExc_KeyboardInterrupt); Py_XINCREF(imp_PyExc_KeyboardInterrupt);
Py_XINCREF(imp_PyExc_TypeError); Py_XINCREF(imp_PyExc_TypeError);
Py_XINCREF(imp_PyExc_ValueError); Py_XINCREF(imp_PyExc_ValueError);
Py_XINCREF(imp_PyExc_SystemExit);
Py_XINCREF(imp_PyExc_RuntimeError); Py_XINCREF(imp_PyExc_RuntimeError);
Py_XINCREF(imp_PyExc_ImportError); Py_XINCREF(imp_PyExc_ImportError);
Py_XINCREF(imp_PyExc_OverflowError); Py_XINCREF(imp_PyExc_OverflowError);

View File

@@ -126,7 +126,6 @@
# define PyErr_PrintEx py3_PyErr_PrintEx # define PyErr_PrintEx py3_PyErr_PrintEx
# define PyErr_NoMemory py3_PyErr_NoMemory # define PyErr_NoMemory py3_PyErr_NoMemory
# define PyErr_Occurred py3_PyErr_Occurred # define PyErr_Occurred py3_PyErr_Occurred
# define PyErr_PrintEx py3_PyErr_PrintEx
# define PyErr_SetNone py3_PyErr_SetNone # define PyErr_SetNone py3_PyErr_SetNone
# define PyErr_SetString py3_PyErr_SetString # define PyErr_SetString py3_PyErr_SetString
# define PyErr_SetObject py3_PyErr_SetObject # define PyErr_SetObject py3_PyErr_SetObject
@@ -403,6 +402,7 @@ static PyObject *p3imp_PyExc_KeyError;
static PyObject *p3imp_PyExc_KeyboardInterrupt; static PyObject *p3imp_PyExc_KeyboardInterrupt;
static PyObject *p3imp_PyExc_TypeError; static PyObject *p3imp_PyExc_TypeError;
static PyObject *p3imp_PyExc_ValueError; static PyObject *p3imp_PyExc_ValueError;
static PyObject *p3imp_PyExc_SystemExit;
static PyObject *p3imp_PyExc_RuntimeError; static PyObject *p3imp_PyExc_RuntimeError;
static PyObject *p3imp_PyExc_ImportError; static PyObject *p3imp_PyExc_ImportError;
static PyObject *p3imp_PyExc_OverflowError; static PyObject *p3imp_PyExc_OverflowError;
@@ -413,6 +413,7 @@ static PyObject *p3imp_PyExc_OverflowError;
# define PyExc_KeyboardInterrupt p3imp_PyExc_KeyboardInterrupt # define PyExc_KeyboardInterrupt p3imp_PyExc_KeyboardInterrupt
# define PyExc_TypeError p3imp_PyExc_TypeError # define PyExc_TypeError p3imp_PyExc_TypeError
# define PyExc_ValueError p3imp_PyExc_ValueError # define PyExc_ValueError p3imp_PyExc_ValueError
# define PyExc_SystemExit p3imp_PyExc_SystemExit
# define PyExc_RuntimeError p3imp_PyExc_RuntimeError # define PyExc_RuntimeError p3imp_PyExc_RuntimeError
# define PyExc_ImportError p3imp_PyExc_ImportError # define PyExc_ImportError p3imp_PyExc_ImportError
# define PyExc_OverflowError p3imp_PyExc_OverflowError # define PyExc_OverflowError p3imp_PyExc_OverflowError
@@ -681,6 +682,7 @@ get_py3_exceptions()
p3imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt"); p3imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt");
p3imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError"); p3imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError");
p3imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError"); p3imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError");
p3imp_PyExc_SystemExit = PyDict_GetItemString(exdict, "SystemExit");
p3imp_PyExc_RuntimeError = PyDict_GetItemString(exdict, "RuntimeError"); p3imp_PyExc_RuntimeError = PyDict_GetItemString(exdict, "RuntimeError");
p3imp_PyExc_ImportError = PyDict_GetItemString(exdict, "ImportError"); p3imp_PyExc_ImportError = PyDict_GetItemString(exdict, "ImportError");
p3imp_PyExc_OverflowError = PyDict_GetItemString(exdict, "OverflowError"); p3imp_PyExc_OverflowError = PyDict_GetItemString(exdict, "OverflowError");
@@ -690,6 +692,7 @@ get_py3_exceptions()
Py_XINCREF(p3imp_PyExc_KeyboardInterrupt); Py_XINCREF(p3imp_PyExc_KeyboardInterrupt);
Py_XINCREF(p3imp_PyExc_TypeError); Py_XINCREF(p3imp_PyExc_TypeError);
Py_XINCREF(p3imp_PyExc_ValueError); Py_XINCREF(p3imp_PyExc_ValueError);
Py_XINCREF(p3imp_PyExc_SystemExit);
Py_XINCREF(p3imp_PyExc_RuntimeError); Py_XINCREF(p3imp_PyExc_RuntimeError);
Py_XINCREF(p3imp_PyExc_ImportError); Py_XINCREF(p3imp_PyExc_ImportError);
Py_XINCREF(p3imp_PyExc_OverflowError); Py_XINCREF(p3imp_PyExc_OverflowError);

View File

@@ -728,6 +728,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1287,
/**/ /**/
1286, 1286,
/**/ /**/