Skip to content

Commit 75b6a89

Browse files
committed
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)
1 parent 3143d93 commit 75b6a89

File tree

5 files changed

+69
-18
lines changed

5 files changed

+69
-18
lines changed

runtime/doc/if_pyth.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,11 @@ To work around such problems there are these options:
740740
3. You undefine PY_NO_RTLD_GLOBAL in auto/config.h after configuration. This
741741
may crash Vim though.
742742

743+
*E880*
744+
Raising SystemExit exception in python isn't endorsed way to quit vim, use: >
745+
:py vim.command("qall!")
746+
<
747+
743748
*has-python*
744749
You can test what Python version is available with: >
745750
if has('python')

src/if_py_both.h

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* Common code for if_python.c and if_python3.c.
1414
*/
1515

16+
static char_u e_py_systemexit[] = "E880: Can't handle SystemExit of %s exception in vim";
17+
1618
#if PY_VERSION_HEX < 0x02050000
1719
typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */
1820
#endif
@@ -275,7 +277,7 @@ ObjectDir(PyObject *self, char **attributes)
275277

276278
if (self)
277279
for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method)
278-
if (add_string(ret, (char *) method->ml_name))
280+
if (add_string(ret, (char *)method->ml_name))
279281
{
280282
Py_DECREF(ret);
281283
return NULL;
@@ -549,8 +551,9 @@ VimTryStart(void)
549551
VimTryEnd(void)
550552
{
551553
--trylevel;
552-
/* Without this it stops processing all subsequent VimL commands and
553-
* generates strange error messages if I e.g. try calling Test() in a cycle */
554+
/* Without this it stops processing all subsequent VimL commands and
555+
* generates strange error messages if I e.g. try calling Test() in a
556+
* cycle */
554557
did_emsg = FALSE;
555558
/* Keyboard interrupt should be preferred over anything else */
556559
if (got_int)
@@ -570,7 +573,7 @@ VimTryEnd(void)
570573
/* Finally transform VimL exception to python one */
571574
else
572575
{
573-
PyErr_SetVim((char *) current_exception->value);
576+
PyErr_SetVim((char *)current_exception->value);
574577
discard_current_exception();
575578
return -1;
576579
}
@@ -667,15 +670,15 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
667670

668671
/* For backwards compatibility numbers are stored as strings. */
669672
sprintf(buf, "%ld", (long)our_tv->vval.v_number);
670-
ret = PyString_FromString((char *) buf);
673+
ret = PyString_FromString((char *)buf);
671674
}
672675
# ifdef FEAT_FLOAT
673676
else if (our_tv->v_type == VAR_FLOAT)
674677
{
675678
char buf[NUMBUFLEN];
676679

677680
sprintf(buf, "%f", our_tv->vval.v_float);
678-
ret = PyString_FromString((char *) buf);
681+
ret = PyString_FromString((char *)buf);
679682
}
680683
# endif
681684
else if (our_tv->v_type == VAR_LIST)
@@ -955,7 +958,7 @@ map_rtp_callback(char_u *path, void *_data)
955958
PyObject *pathObject;
956959
map_rtp_data *mr_data = *((map_rtp_data **) data);
957960

958-
if (!(pathObject = PyString_FromString((char *) path)))
961+
if (!(pathObject = PyString_FromString((char *)path)))
959962
{
960963
*data = NULL;
961964
return;
@@ -1124,7 +1127,7 @@ find_module(char *fullname, char *tail, PyObject *new_path)
11241127
PyObject *module;
11251128
char *dot;
11261129

1127-
if ((dot = (char *) vim_strchr((char_u *) tail, '.')))
1130+
if ((dot = (char *)vim_strchr((char_u *) tail, '.')))
11281131
{
11291132
/*
11301133
* There is a dot in the name: call find_module recursively without the
@@ -1658,7 +1661,7 @@ DictionaryIterNext(dictiterinfo_T **dii)
16581661

16591662
--((*dii)->todo);
16601663

1661-
if (!(ret = PyBytes_FromString((char *) (*dii)->hi->hi_key)))
1664+
if (!(ret = PyBytes_FromString((char *)(*dii)->hi->hi_key)))
16621665
return NULL;
16631666

16641667
return ret;
@@ -2680,12 +2683,12 @@ FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
26802683
FunctionRepr(FunctionObject *self)
26812684
{
26822685
#ifdef Py_TRACE_REFS
2683-
/* For unknown reason self->name may be NULL after calling
2686+
/* For unknown reason self->name may be NULL after calling
26842687
* Finalize */
26852688
return PyString_FromFormat("<vim.Function '%s'>",
2686-
(self->name == NULL ? "<NULL>" : (char *) self->name));
2689+
(self->name == NULL ? "<NULL>" : (char *)self->name));
26872690
#else
2688-
return PyString_FromFormat("<vim.Function '%s'>", (char *) self->name);
2691+
return PyString_FromFormat("<vim.Function '%s'>", (char *)self->name);
26892692
#endif
26902693
}
26912694

@@ -2809,7 +2812,7 @@ OptionsItem(OptionsObject *self, PyObject *keyObject)
28092812
{
28102813
if (stringval)
28112814
{
2812-
PyObject *ret = PyBytes_FromString((char *) stringval);
2815+
PyObject *ret = PyBytes_FromString((char *)stringval);
28132816
vim_free(stringval);
28142817
return ret;
28152818
}
@@ -4525,7 +4528,7 @@ BufferAttr(BufferObject *self, char *name)
45254528
{
45264529
if (strcmp(name, "name") == 0)
45274530
return PyString_FromString((self->buf->b_ffname == NULL
4528-
? "" : (char *) self->buf->b_ffname));
4531+
? "" : (char *)self->buf->b_ffname));
45294532
else if (strcmp(name, "number") == 0)
45304533
return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
45314534
else if (strcmp(name, "vars") == 0)
@@ -4961,7 +4964,19 @@ run_cmd(const char *cmd, void *arg UNUSED
49614964
#endif
49624965
)
49634966
{
4964-
PyRun_SimpleString((char *) cmd);
4967+
PyObject *run_ret;
4968+
run_ret = PyRun_String((char *)cmd, Py_file_input, globals, globals);
4969+
if (run_ret != NULL)
4970+
{
4971+
Py_DECREF(run_ret);
4972+
}
4973+
else if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit))
4974+
{
4975+
EMSG2(_(e_py_systemexit), "python");
4976+
PyErr_Clear();
4977+
}
4978+
else
4979+
PyErr_PrintEx(1);
49654980
}
49664981

49674982
static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
@@ -4979,6 +4994,7 @@ run_do(const char *cmd, void *arg UNUSED
49794994
char *code;
49804995
int status;
49814996
PyObject *pyfunc, *pymain;
4997+
PyObject *run_ret;
49824998

49834999
if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK)
49845000
{
@@ -4990,7 +5006,23 @@ run_do(const char *cmd, void *arg UNUSED
49905006
code = PyMem_New(char, len + 1);
49915007
memcpy(code, code_hdr, code_hdr_len);
49925008
STRCPY(code + code_hdr_len, cmd);
4993-
status = PyRun_SimpleString(code);
5009+
run_ret = PyRun_String(code, Py_file_input, globals, globals);
5010+
status = -1;
5011+
if (run_ret != NULL)
5012+
{
5013+
status = 0;
5014+
Py_DECREF(run_ret);
5015+
}
5016+
else if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit))
5017+
{
5018+
PyMem_Free(code);
5019+
EMSG2(_(e_py_systemexit), "python");
5020+
PyErr_Clear();
5021+
return;
5022+
}
5023+
else
5024+
PyErr_PrintEx(1);
5025+
49945026
PyMem_Free(code);
49955027

49965028
if (status)
@@ -5068,9 +5100,14 @@ run_eval(const char *cmd, typval_T *rettv
50685100
{
50695101
PyObject *run_ret;
50705102

5071-
run_ret = PyRun_String((char *) cmd, Py_eval_input, globals, globals);
5103+
run_ret = PyRun_String((char *)cmd, Py_eval_input, globals, globals);
50725104
if (run_ret == NULL)
50735105
{
5106+
if (PyErr_ExceptionMatches(PyExc_SystemExit))
5107+
{
5108+
EMSG2(_(e_py_systemexit), "python");
5109+
PyErr_Clear();
5110+
}
50745111
if (PyErr_Occurred() && !msg_silent)
50755112
PyErr_PrintEx(0);
50765113
EMSG(_("E858: Eval did not return a valid python object"));

src/if_python.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ static PyObject *imp_PyExc_KeyError;
444444
static PyObject *imp_PyExc_KeyboardInterrupt;
445445
static PyObject *imp_PyExc_TypeError;
446446
static PyObject *imp_PyExc_ValueError;
447+
static PyObject *imp_PyExc_SystemExit;
447448
static PyObject *imp_PyExc_RuntimeError;
448449
static PyObject *imp_PyExc_ImportError;
449450
static PyObject *imp_PyExc_OverflowError;
@@ -454,6 +455,7 @@ static PyObject *imp_PyExc_OverflowError;
454455
# define PyExc_KeyboardInterrupt imp_PyExc_KeyboardInterrupt
455456
# define PyExc_TypeError imp_PyExc_TypeError
456457
# define PyExc_ValueError imp_PyExc_ValueError
458+
# define PyExc_SystemExit imp_PyExc_SystemExit
457459
# define PyExc_RuntimeError imp_PyExc_RuntimeError
458460
# define PyExc_ImportError imp_PyExc_ImportError
459461
# define PyExc_OverflowError imp_PyExc_OverflowError
@@ -731,6 +733,7 @@ get_exceptions(void)
731733
imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt");
732734
imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError");
733735
imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError");
736+
imp_PyExc_SystemExit = PyDict_GetItemString(exdict, "SystemExit");
734737
imp_PyExc_RuntimeError = PyDict_GetItemString(exdict, "RuntimeError");
735738
imp_PyExc_ImportError = PyDict_GetItemString(exdict, "ImportError");
736739
imp_PyExc_OverflowError = PyDict_GetItemString(exdict, "OverflowError");
@@ -740,6 +743,7 @@ get_exceptions(void)
740743
Py_XINCREF(imp_PyExc_KeyboardInterrupt);
741744
Py_XINCREF(imp_PyExc_TypeError);
742745
Py_XINCREF(imp_PyExc_ValueError);
746+
Py_XINCREF(imp_PyExc_SystemExit);
743747
Py_XINCREF(imp_PyExc_RuntimeError);
744748
Py_XINCREF(imp_PyExc_ImportError);
745749
Py_XINCREF(imp_PyExc_OverflowError);

src/if_python3.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@
126126
# define PyErr_PrintEx py3_PyErr_PrintEx
127127
# define PyErr_NoMemory py3_PyErr_NoMemory
128128
# define PyErr_Occurred py3_PyErr_Occurred
129-
# define PyErr_PrintEx py3_PyErr_PrintEx
130129
# define PyErr_SetNone py3_PyErr_SetNone
131130
# define PyErr_SetString py3_PyErr_SetString
132131
# define PyErr_SetObject py3_PyErr_SetObject
@@ -403,6 +402,7 @@ static PyObject *p3imp_PyExc_KeyError;
403402
static PyObject *p3imp_PyExc_KeyboardInterrupt;
404403
static PyObject *p3imp_PyExc_TypeError;
405404
static PyObject *p3imp_PyExc_ValueError;
405+
static PyObject *p3imp_PyExc_SystemExit;
406406
static PyObject *p3imp_PyExc_RuntimeError;
407407
static PyObject *p3imp_PyExc_ImportError;
408408
static PyObject *p3imp_PyExc_OverflowError;
@@ -413,6 +413,7 @@ static PyObject *p3imp_PyExc_OverflowError;
413413
# define PyExc_KeyboardInterrupt p3imp_PyExc_KeyboardInterrupt
414414
# define PyExc_TypeError p3imp_PyExc_TypeError
415415
# define PyExc_ValueError p3imp_PyExc_ValueError
416+
# define PyExc_SystemExit p3imp_PyExc_SystemExit
416417
# define PyExc_RuntimeError p3imp_PyExc_RuntimeError
417418
# define PyExc_ImportError p3imp_PyExc_ImportError
418419
# define PyExc_OverflowError p3imp_PyExc_OverflowError
@@ -681,6 +682,7 @@ get_py3_exceptions()
681682
p3imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt");
682683
p3imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError");
683684
p3imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError");
685+
p3imp_PyExc_SystemExit = PyDict_GetItemString(exdict, "SystemExit");
684686
p3imp_PyExc_RuntimeError = PyDict_GetItemString(exdict, "RuntimeError");
685687
p3imp_PyExc_ImportError = PyDict_GetItemString(exdict, "ImportError");
686688
p3imp_PyExc_OverflowError = PyDict_GetItemString(exdict, "OverflowError");
@@ -690,6 +692,7 @@ get_py3_exceptions()
690692
Py_XINCREF(p3imp_PyExc_KeyboardInterrupt);
691693
Py_XINCREF(p3imp_PyExc_TypeError);
692694
Py_XINCREF(p3imp_PyExc_ValueError);
695+
Py_XINCREF(p3imp_PyExc_SystemExit);
693696
Py_XINCREF(p3imp_PyExc_RuntimeError);
694697
Py_XINCREF(p3imp_PyExc_ImportError);
695698
Py_XINCREF(p3imp_PyExc_OverflowError);

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,8 @@ static char *(features[]) =
728728

729729
static int included_patches[] =
730730
{ /* Add new patch number below this line */
731+
/**/
732+
1287,
731733
/**/
732734
1286,
733735
/**/

0 commit comments

Comments
 (0)