bpo-36829: Enhance PyErr_WriteUnraisable() (GH-13487) · python/cpython@a58db96 (original) (raw)

`@@ -940,90 +940,121 @@ PyErr_NewExceptionWithDoc(const char *name, const char *doc,

`

940

940

`}

`

941

941

``

942

942

``

943

``

`-

/* Call when an exception has occurred but there is no way for Python

`

944

``

`-

to handle it. Examples: exception in del or during GC. */

`

945

``

`-

void

`

946

``

`-

PyErr_WriteUnraisable(PyObject *obj)

`

``

943

`+

static void

`

``

944

`+

write_unraisable_exc_file(PyObject *exc_type, PyObject *exc_value,

`

``

945

`+

PyObject *exc_tb, PyObject *obj, PyObject *file)

`

947

946

`{

`

948

``

`-

_Py_IDENTIFIER(module);

`

949

``

`-

PyObject *f, *t, *v, *tb;

`

950

``

`-

PyObject *moduleName = NULL;

`

951

``

`-

char* className;

`

952

``

-

953

``

`-

PyErr_Fetch(&t, &v, &tb);

`

954

``

-

955

``

`-

f = _PySys_GetObjectId(&PyId_stderr);

`

956

``

`-

if (f == NULL || f == Py_None)

`

957

``

`-

goto done;

`

958

``

-

959

947

`if (obj) {

`

960

``

`-

if (PyFile_WriteString("Exception ignored in: ", f) < 0)

`

961

``

`-

goto done;

`

962

``

`-

if (PyFile_WriteObject(obj, f, 0) < 0) {

`

``

948

`+

if (PyFile_WriteString("Exception ignored in: ", file) < 0) {

`

``

949

`+

return;

`

``

950

`+

}

`

``

951

`+

if (PyFile_WriteObject(obj, file, 0) < 0) {

`

963

952

`PyErr_Clear();

`

964

``

`-

if (PyFile_WriteString("<object repr() failed>", f) < 0) {

`

965

``

`-

goto done;

`

``

953

`+

if (PyFile_WriteString("<object repr() failed>", file) < 0) {

`

``

954

`+

return;

`

966

955

` }

`

967

956

` }

`

968

``

`-

if (PyFile_WriteString("\n", f) < 0)

`

969

``

`-

goto done;

`

``

957

`+

if (PyFile_WriteString("\n", file) < 0) {

`

``

958

`+

return;

`

``

959

`+

}

`

970

960

` }

`

971

961

``

972

``

`-

if (PyTraceBack_Print(tb, f) < 0)

`

973

``

`-

goto done;

`

``

962

`+

if (exc_tb != NULL) {

`

``

963

`+

if (PyTraceBack_Print(exc_tb, file) < 0) {

`

``

964

`+

/* continue even if writing the traceback failed */

`

``

965

`+

PyErr_Clear();

`

``

966

`+

}

`

``

967

`+

}

`

974

968

``

975

``

`-

if (!t)

`

976

``

`-

goto done;

`

``

969

`+

if (!exc_type) {

`

``

970

`+

return;

`

``

971

`+

}

`

977

972

``

978

``

`-

assert(PyExceptionClass_Check(t));

`

979

``

`-

className = PyExceptionClass_Name(t);

`

``

973

`+

assert(PyExceptionClass_Check(exc_type));

`

``

974

`+

char* className = PyExceptionClass_Name(exc_type);

`

980

975

`if (className != NULL) {

`

981

976

`char *dot = strrchr(className, '.');

`

982

``

`-

if (dot != NULL)

`

``

977

`+

if (dot != NULL) {

`

983

978

`className = dot+1;

`

``

979

`+

}

`

984

980

` }

`

985

981

``

986

``

`-

moduleName = PyObject_GetAttrId(t, &PyId___module_);

`

``

982

`+

_Py_IDENTIFIER(module);

`

``

983

`+

PyObject *moduleName = PyObject_GetAttrId(exc_type, &PyId___module_);

`

987

984

`if (moduleName == NULL || !PyUnicode_Check(moduleName)) {

`

``

985

`+

Py_XDECREF(moduleName);

`

988

986

`PyErr_Clear();

`

989

``

`-

if (PyFile_WriteString("", f) < 0)

`

990

``

`-

goto done;

`

``

987

`+

if (PyFile_WriteString("", file) < 0) {

`

``

988

`+

return;

`

``

989

`+

}

`

991

990

` }

`

992

991

`else {

`

993

992

`if (!_PyUnicode_EqualToASCIIId(moduleName, &PyId_builtins)) {

`

994

``

`-

if (PyFile_WriteObject(moduleName, f, Py_PRINT_RAW) < 0)

`

995

``

`-

goto done;

`

996

``

`-

if (PyFile_WriteString(".", f) < 0)

`

997

``

`-

goto done;

`

``

993

`+

if (PyFile_WriteObject(moduleName, file, Py_PRINT_RAW) < 0) {

`

``

994

`+

Py_DECREF(moduleName);

`

``

995

`+

return;

`

``

996

`+

}

`

``

997

`+

Py_DECREF(moduleName);

`

``

998

`+

if (PyFile_WriteString(".", file) < 0) {

`

``

999

`+

return;

`

``

1000

`+

}

`

``

1001

`+

}

`

``

1002

`+

else {

`

``

1003

`+

Py_DECREF(moduleName);

`

998

1004

` }

`

999

1005

` }

`

``

1006

+

1000

1007

`if (className == NULL) {

`

1001

``

`-

if (PyFile_WriteString("", f) < 0)

`

1002

``

`-

goto done;

`

``

1008

`+

if (PyFile_WriteString("", file) < 0) {

`

``

1009

`+

return;

`

``

1010

`+

}

`

1003

1011

` }

`

1004

1012

`else {

`

1005

``

`-

if (PyFile_WriteString(className, f) < 0)

`

1006

``

`-

goto done;

`

``

1013

`+

if (PyFile_WriteString(className, file) < 0) {

`

``

1014

`+

return;

`

``

1015

`+

}

`

1007

1016

` }

`

1008

1017

``

1009

``

`-

if (v && v != Py_None) {

`

1010

``

`-

if (PyFile_WriteString(": ", f) < 0)

`

1011

``

`-

goto done;

`

1012

``

`-

if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0) {

`

``

1018

`+

if (exc_value && exc_value != Py_None) {

`

``

1019

`+

if (PyFile_WriteString(": ", file) < 0) {

`

``

1020

`+

return;

`

``

1021

`+

}

`

``

1022

`+

if (PyFile_WriteObject(exc_value, file, Py_PRINT_RAW) < 0) {

`

1013

1023

`PyErr_Clear();

`

1014

``

`-

if (PyFile_WriteString("<exception str() failed>", f) < 0) {

`

1015

``

`-

goto done;

`

``

1024

`+

if (PyFile_WriteString("<exception str() failed>", file) < 0) {

`

``

1025

`+

return;

`

1016

1026

` }

`

1017

1027

` }

`

1018

1028

` }

`

1019

``

`-

if (PyFile_WriteString("\n", f) < 0)

`

1020

``

`-

goto done;

`

``

1029

`+

if (PyFile_WriteString("\n", file) < 0) {

`

``

1030

`+

return;

`

``

1031

`+

}

`

``

1032

`+

}

`

1021

1033

``

1022

``

`-

done:

`

1023

``

`-

Py_XDECREF(moduleName);

`

1024

``

`-

Py_XDECREF(t);

`

1025

``

`-

Py_XDECREF(v);

`

1026

``

`-

Py_XDECREF(tb);

`

``

1034

+

``

1035

`+

/* Display an unraisable exception into sys.stderr.

`

``

1036

+

``

1037

`+

Called when an exception has occurred but there is no way for Python to

`

``

1038

`+

handle it. For example, when a destructor raises an exception or during

`

``

1039

`+

garbage collection (gc.collect()).

`

``

1040

+

``

1041

`+

An exception must be set when calling this function. */

`

``

1042

`+

void

`

``

1043

`+

PyErr_WriteUnraisable(PyObject *obj)

`

``

1044

`+

{

`

``

1045

`+

PyObject *f, *exc_type, *exc_value, *exc_tb;

`

``

1046

+

``

1047

`+

PyErr_Fetch(&exc_type, &exc_value, &exc_tb);

`

``

1048

+

``

1049

`+

f = _PySys_GetObjectId(&PyId_stderr);

`

``

1050

`+

/* Do nothing if sys.stderr is not available or set to None */

`

``

1051

`+

if (f != NULL && f != Py_None) {

`

``

1052

`+

write_unraisable_exc_file(exc_type, exc_value, exc_tb, obj, f);

`

``

1053

`+

}

`

``

1054

+

``

1055

`+

Py_XDECREF(exc_type);

`

``

1056

`+

Py_XDECREF(exc_value);

`

``

1057

`+

Py_XDECREF(exc_tb);

`

1027

1058

`PyErr_Clear(); /* Just in case */

`

1028

1059

`}

`

1029

1060

``