Skip to content

Commit 87d3b9d

Browse files
authored
bpo-39882: Add _Py_FatalErrorFormat() function (GH-19157)
1 parent ace018c commit 87d3b9d

File tree

15 files changed

+157
-109
lines changed

15 files changed

+157
-109
lines changed

Include/cpython/pyerrors.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFunc(
182182
const char *func,
183183
const char *message);
184184

185+
PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFormat(
186+
const char *func,
187+
const char *format,
188+
...);
189+
185190
#define Py_FatalError(message) _Py_FatalErrorFunc(__func__, message)
186191

187192
#ifdef __cplusplus

Modules/_io/bufferedio.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -292,12 +292,11 @@ _enter_buffered_busy(buffered *self)
292292
}
293293
Py_END_ALLOW_THREADS
294294
if (relax_locking && st != PY_LOCK_ACQUIRED) {
295-
PyObject *msgobj = PyUnicode_FromFormat(
296-
"could not acquire lock for %A at interpreter "
295+
PyObject *ascii = PyObject_ASCII((PyObject*)self);
296+
_Py_FatalErrorFormat(__func__,
297+
"could not acquire lock for %s at interpreter "
297298
"shutdown, possibly due to daemon threads",
298-
(PyObject *) self);
299-
const char *msg = PyUnicode_AsUTF8(msgobj);
300-
Py_FatalError(msg);
299+
ascii ? PyUnicode_AsUTF8(ascii) : "<ascii(self) failed>");
301300
}
302301
return 1;
303302
}

Objects/call.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ _Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable,
4646
"%s returned NULL without setting an error",
4747
where);
4848
#ifdef Py_DEBUG
49-
/* Ensure that the bug is caught in debug mode */
49+
/* Ensure that the bug is caught in debug mode.
50+
Py_FatalError() logs the SystemError exception raised above. */
5051
Py_FatalError("a function returned NULL without setting an error");
5152
#endif
5253
return NULL;
@@ -67,7 +68,8 @@ _Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable,
6768
"%s returned a result with an error set", where);
6869
}
6970
#ifdef Py_DEBUG
70-
/* Ensure that the bug is caught in debug mode */
71+
/* Ensure that the bug is caught in debug mode.
72+
Py_FatalError() logs the SystemError exception raised above. */
7173
Py_FatalError("a function returned a result with an error set");
7274
#endif
7375
return NULL;

Objects/frameobject.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -957,8 +957,9 @@ void
957957
PyFrame_BlockSetup(PyFrameObject *f, int type, int handler, int level)
958958
{
959959
PyTryBlock *b;
960-
if (f->f_iblock >= CO_MAXBLOCKS)
961-
Py_FatalError("XXX block stack overflow");
960+
if (f->f_iblock >= CO_MAXBLOCKS) {
961+
Py_FatalError("block stack overflow");
962+
}
962963
b = &f->f_blockstack[f->f_iblock++];
963964
b->b_type = type;
964965
b->b_level = level;
@@ -969,8 +970,9 @@ PyTryBlock *
969970
PyFrame_BlockPop(PyFrameObject *f)
970971
{
971972
PyTryBlock *b;
972-
if (f->f_iblock <= 0)
973-
Py_FatalError("XXX block stack underflow");
973+
if (f->f_iblock <= 0) {
974+
Py_FatalError("block stack underflow");
975+
}
974976
b = &f->f_blockstack[--f->f_iblock];
975977
return b;
976978
}

Objects/obmalloc.c

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2361,26 +2361,22 @@ _PyMem_DebugRealloc(void *ctx, void *ptr, size_t nbytes)
23612361
static void
23622362
_PyMem_DebugCheckAddress(const char *func, char api, const void *p)
23632363
{
2364+
assert(p != NULL);
2365+
23642366
const uint8_t *q = (const uint8_t *)p;
2365-
char msgbuf[64];
2366-
const char *msg;
23672367
size_t nbytes;
23682368
const uint8_t *tail;
23692369
int i;
23702370
char id;
23712371

2372-
if (p == NULL) {
2373-
msg = "didn't expect a NULL pointer";
2374-
goto error;
2375-
}
2376-
23772372
/* Check the API id */
23782373
id = (char)q[-SST];
23792374
if (id != api) {
2380-
msg = msgbuf;
2381-
snprintf(msgbuf, sizeof(msgbuf), "bad ID: Allocated using API '%c', verified using API '%c'", id, api);
2382-
msgbuf[sizeof(msgbuf)-1] = 0;
2383-
goto error;
2375+
_PyObject_DebugDumpAddress(p);
2376+
_Py_FatalErrorFormat(func,
2377+
"bad ID: Allocated using API '%c', "
2378+
"verified using API '%c'",
2379+
id, api);
23842380
}
23852381

23862382
/* Check the stuff at the start of p first: if there's underwrite
@@ -2389,25 +2385,19 @@ _PyMem_DebugCheckAddress(const char *func, char api, const void *p)
23892385
*/
23902386
for (i = SST-1; i >= 1; --i) {
23912387
if (*(q-i) != PYMEM_FORBIDDENBYTE) {
2392-
msg = "bad leading pad byte";
2393-
goto error;
2388+
_PyObject_DebugDumpAddress(p);
2389+
_Py_FatalErrorFunc(func, "bad leading pad byte");
23942390
}
23952391
}
23962392

23972393
nbytes = read_size_t(q - 2*SST);
23982394
tail = q + nbytes;
23992395
for (i = 0; i < SST; ++i) {
24002396
if (tail[i] != PYMEM_FORBIDDENBYTE) {
2401-
msg = "bad trailing pad byte";
2402-
goto error;
2397+
_PyObject_DebugDumpAddress(p);
2398+
_Py_FatalErrorFunc(func, "bad trailing pad byte");
24032399
}
24042400
}
2405-
2406-
return;
2407-
2408-
error:
2409-
_PyObject_DebugDumpAddress(p);
2410-
_Py_FatalErrorFunc(func, msg);
24112401
}
24122402

24132403
/* Display info to stderr about the memory block at p. */

Parser/grammar1.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ PyGrammar_LabelRepr(label *lb)
4141
}
4242
}
4343
else {
44-
Py_FatalError("invalid label");
44+
Py_FatalError("invalid grammar label");
4545
return NULL;
4646
}
4747
}

Parser/tokenizer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,7 @@ tok_backup(struct tok_state *tok, int c)
10321032
{
10331033
if (c != EOF) {
10341034
if (--tok->cur < tok->buf) {
1035-
Py_FatalError("beginning of buffer");
1035+
Py_FatalError("tokenizer beginning of buffer");
10361036
}
10371037
if (*tok->cur != c) {
10381038
*tok->cur = c;

Python/ast.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -727,11 +727,8 @@ num_stmts(const node *n)
727727
return l;
728728
}
729729
default: {
730-
char buf[128];
731-
732-
sprintf(buf, "Non-statement found: %d %d",
733-
TYPE(n), NCH(n));
734-
Py_FatalError(buf);
730+
_Py_FatalErrorFormat(__func__, "Non-statement found: %d %d",
731+
TYPE(n), NCH(n));
735732
}
736733
}
737734
Py_UNREACHABLE();
@@ -1664,7 +1661,7 @@ ast_for_decorator(struct compiling *c, const node *n)
16641661
REQ(n, decorator);
16651662
REQ(CHILD(n, 0), AT);
16661663
REQ(CHILD(n, 2), NEWLINE);
1667-
1664+
16681665
return ast_for_expr(c, CHILD(n, 1));
16691666
}
16701667

Python/compile.c

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,18 +1876,15 @@ get_ref_type(struct compiler *c, PyObject *name)
18761876
return CELL;
18771877
scope = PyST_GetScope(c->u->u_ste, name);
18781878
if (scope == 0) {
1879-
char buf[350];
1880-
PyOS_snprintf(buf, sizeof(buf),
1881-
"unknown scope for %.100s in %.100s(%s)\n"
1882-
"symbols: %s\nlocals: %s\nglobals: %s",
1883-
PyUnicode_AsUTF8(name),
1884-
PyUnicode_AsUTF8(c->u->u_name),
1885-
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_id)),
1886-
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_symbols)),
1887-
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_varnames)),
1888-
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_names))
1889-
);
1890-
Py_FatalError(buf);
1879+
_Py_FatalErrorFormat(__func__,
1880+
"unknown scope for %.100s in %.100s(%s)\n"
1881+
"symbols: %s\nlocals: %s\nglobals: %s",
1882+
PyUnicode_AsUTF8(name),
1883+
PyUnicode_AsUTF8(c->u->u_name),
1884+
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_id)),
1885+
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_symbols)),
1886+
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_varnames)),
1887+
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_names)));
18911888
}
18921889

18931890
return scope;
@@ -1930,15 +1927,14 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags, Py
19301927
else /* (reftype == FREE) */
19311928
arg = compiler_lookup_arg(c->u->u_freevars, name);
19321929
if (arg == -1) {
1933-
fprintf(stderr,
1930+
_Py_FatalErrorFormat(__func__,
19341931
"lookup %s in %s %d %d\n"
19351932
"freevars of %s: %s\n",
19361933
PyUnicode_AsUTF8(PyObject_Repr(name)),
19371934
PyUnicode_AsUTF8(c->u->u_name),
19381935
reftype, arg,
19391936
PyUnicode_AsUTF8(co->co_name),
19401937
PyUnicode_AsUTF8(PyObject_Repr(co->co_freevars)));
1941-
Py_FatalError("compiler_make_closure()");
19421938
}
19431939
ADDOP_I(c, LOAD_CLOSURE, arg);
19441940
}
@@ -5411,8 +5407,8 @@ stackdepth(struct compiler *c)
54115407
struct instr *instr = &b->b_instr[i];
54125408
int effect = stack_effect(instr->i_opcode, instr->i_oparg, 0);
54135409
if (effect == PY_INVALID_STACK_EFFECT) {
5414-
fprintf(stderr, "opcode = %d\n", instr->i_opcode);
5415-
Py_FatalError("PyCompile_OpcodeStackEffect()");
5410+
_Py_FatalErrorFormat(__func__,
5411+
"opcode = %d", instr->i_opcode);
54165412
}
54175413
int new_depth = depth + effect;
54185414
if (new_depth > maxdepth) {

Python/frozenmain.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ Py_FrozenMain(int argc, char **argv)
9999

100100
n = PyImport_ImportFrozenModule("__main__");
101101
if (n == 0)
102-
Py_FatalError("__main__ not frozen");
102+
Py_FatalError("the __main__ module is not frozen");
103103
if (n < 0) {
104104
PyErr_Print();
105105
sts = 1;

Python/import.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ _PyImport_ReInitLock(void)
209209
if (import_lock != NULL) {
210210
import_lock = PyThread_allocate_lock();
211211
if (import_lock == NULL) {
212-
Py_FatalError("PyImport_ReInitLock failed to create a new lock");
212+
_Py_FatalErrorFunc(__func__, "failed to create a new lock");
213213
}
214214
}
215215
if (import_lock_level > 1) {
@@ -310,7 +310,7 @@ PyImport_GetModuleDict(void)
310310
{
311311
PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
312312
if (interp->modules == NULL) {
313-
Py_FatalError("no module dictionary");
313+
Py_FatalError("interpreter has no modules dictionary");
314314
}
315315
return interp->modules;
316316
}
@@ -982,7 +982,7 @@ PyImport_ExecCodeModuleWithPathnames(const char *name, PyObject *co,
982982
_Py_IDENTIFIER(_get_sourcefile);
983983

984984
if (interp == NULL) {
985-
Py_FatalError("no interpreter!");
985+
Py_FatalError("no current interpreter");
986986
}
987987

988988
external= PyObject_GetAttrString(interp->importlib,

Python/mysnprintf.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,12 @@ PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
8181
}
8282

8383
len = vsprintf(buffer, format, va);
84-
if (len < 0)
84+
if (len < 0) {
8585
/* ignore the error */;
86-
87-
else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
88-
Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
89-
86+
}
87+
else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE) {
88+
_Py_FatalErrorFunc(__func__, "Buffer overflow");
89+
}
9090
else {
9191
const size_t to_copy = (size_t)len < size ?
9292
(size_t)len : size - 1;

Python/pathconfig.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,12 @@ pathconfig_global_init(void)
484484

485485
/* External interface */
486486

487+
static void _Py_NO_RETURN
488+
path_out_of_memory(const char *func)
489+
{
490+
_Py_FatalErrorFunc(func, "out of memory");
491+
}
492+
487493
void
488494
Py_SetPath(const wchar_t *path)
489495
{
@@ -515,7 +521,7 @@ Py_SetPath(const wchar_t *path)
515521
|| _Py_path_config.exec_prefix == NULL
516522
|| _Py_path_config.module_search_path == NULL)
517523
{
518-
Py_FatalError("out of memory");
524+
path_out_of_memory(__func__);
519525
}
520526
}
521527

@@ -536,7 +542,7 @@ Py_SetPythonHome(const wchar_t *home)
536542
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
537543

538544
if (_Py_path_config.home == NULL) {
539-
Py_FatalError("out of memory");
545+
path_out_of_memory(__func__);
540546
}
541547
}
542548

@@ -557,7 +563,7 @@ Py_SetProgramName(const wchar_t *program_name)
557563
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
558564

559565
if (_Py_path_config.program_name == NULL) {
560-
Py_FatalError("out of memory");
566+
path_out_of_memory(__func__);
561567
}
562568
}
563569

@@ -577,7 +583,7 @@ _Py_SetProgramFullPath(const wchar_t *program_full_path)
577583
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
578584

579585
if (_Py_path_config.program_full_path == NULL) {
580-
Py_FatalError("out of memory");
586+
path_out_of_memory(__func__);
581587
}
582588
}
583589

0 commit comments

Comments
 (0)