Skip to content

bpo-39882: Add _Py_FatalErrorFormat() function #19157

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Include/cpython/pyerrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFunc(
const char *func,
const char *message);

PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFormat(
const char *func,
const char *format,
...);

#define Py_FatalError(message) _Py_FatalErrorFunc(__func__, message)

#ifdef __cplusplus
Expand Down
9 changes: 4 additions & 5 deletions Modules/_io/bufferedio.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,11 @@ _enter_buffered_busy(buffered *self)
}
Py_END_ALLOW_THREADS
if (relax_locking && st != PY_LOCK_ACQUIRED) {
PyObject *msgobj = PyUnicode_FromFormat(
"could not acquire lock for %A at interpreter "
PyObject *ascii = PyObject_ASCII((PyObject*)self);
_Py_FatalErrorFormat(__func__,
"could not acquire lock for %s at interpreter "
"shutdown, possibly due to daemon threads",
(PyObject *) self);
const char *msg = PyUnicode_AsUTF8(msgobj);
Py_FatalError(msg);
ascii ? PyUnicode_AsUTF8(ascii) : "<ascii(self) failed>");
}
return 1;
}
Expand Down
6 changes: 4 additions & 2 deletions Objects/call.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ _Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable,
"%s returned NULL without setting an error",
where);
#ifdef Py_DEBUG
/* Ensure that the bug is caught in debug mode */
/* Ensure that the bug is caught in debug mode.
Py_FatalError() logs the SystemError exception raised above. */
Py_FatalError("a function returned NULL without setting an error");
#endif
return NULL;
Expand All @@ -67,7 +68,8 @@ _Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable,
"%s returned a result with an error set", where);
}
#ifdef Py_DEBUG
/* Ensure that the bug is caught in debug mode */
/* Ensure that the bug is caught in debug mode.
Py_FatalError() logs the SystemError exception raised above. */
Py_FatalError("a function returned a result with an error set");
#endif
return NULL;
Expand Down
10 changes: 6 additions & 4 deletions Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -957,8 +957,9 @@ void
PyFrame_BlockSetup(PyFrameObject *f, int type, int handler, int level)
{
PyTryBlock *b;
if (f->f_iblock >= CO_MAXBLOCKS)
Py_FatalError("XXX block stack overflow");
if (f->f_iblock >= CO_MAXBLOCKS) {
Py_FatalError("block stack overflow");
}
b = &f->f_blockstack[f->f_iblock++];
b->b_type = type;
b->b_level = level;
Expand All @@ -969,8 +970,9 @@ PyTryBlock *
PyFrame_BlockPop(PyFrameObject *f)
{
PyTryBlock *b;
if (f->f_iblock <= 0)
Py_FatalError("XXX block stack underflow");
if (f->f_iblock <= 0) {
Py_FatalError("block stack underflow");
}
b = &f->f_blockstack[--f->f_iblock];
return b;
}
Expand Down
32 changes: 11 additions & 21 deletions Objects/obmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2361,26 +2361,22 @@ _PyMem_DebugRealloc(void *ctx, void *ptr, size_t nbytes)
static void
_PyMem_DebugCheckAddress(const char *func, char api, const void *p)
{
assert(p != NULL);

const uint8_t *q = (const uint8_t *)p;
char msgbuf[64];
const char *msg;
size_t nbytes;
const uint8_t *tail;
int i;
char id;

if (p == NULL) {
msg = "didn't expect a NULL pointer";
goto error;
}

/* Check the API id */
id = (char)q[-SST];
if (id != api) {
msg = msgbuf;
snprintf(msgbuf, sizeof(msgbuf), "bad ID: Allocated using API '%c', verified using API '%c'", id, api);
msgbuf[sizeof(msgbuf)-1] = 0;
goto error;
_PyObject_DebugDumpAddress(p);
_Py_FatalErrorFormat(func,
"bad ID: Allocated using API '%c', "
"verified using API '%c'",
id, api);
}

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

nbytes = read_size_t(q - 2*SST);
tail = q + nbytes;
for (i = 0; i < SST; ++i) {
if (tail[i] != PYMEM_FORBIDDENBYTE) {
msg = "bad trailing pad byte";
goto error;
_PyObject_DebugDumpAddress(p);
_Py_FatalErrorFunc(func, "bad trailing pad byte");
}
}

return;

error:
_PyObject_DebugDumpAddress(p);
_Py_FatalErrorFunc(func, msg);
}

/* Display info to stderr about the memory block at p. */
Expand Down
2 changes: 1 addition & 1 deletion Parser/grammar1.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ PyGrammar_LabelRepr(label *lb)
}
}
else {
Py_FatalError("invalid label");
Py_FatalError("invalid grammar label");
return NULL;
}
}
2 changes: 1 addition & 1 deletion Parser/tokenizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,7 @@ tok_backup(struct tok_state *tok, int c)
{
if (c != EOF) {
if (--tok->cur < tok->buf) {
Py_FatalError("beginning of buffer");
Py_FatalError("tokenizer beginning of buffer");
}
if (*tok->cur != c) {
*tok->cur = c;
Expand Down
9 changes: 3 additions & 6 deletions Python/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -727,11 +727,8 @@ num_stmts(const node *n)
return l;
}
default: {
char buf[128];

sprintf(buf, "Non-statement found: %d %d",
TYPE(n), NCH(n));
Py_FatalError(buf);
_Py_FatalErrorFormat(__func__, "Non-statement found: %d %d",
TYPE(n), NCH(n));
}
}
Py_UNREACHABLE();
Expand Down Expand Up @@ -1664,7 +1661,7 @@ ast_for_decorator(struct compiling *c, const node *n)
REQ(n, decorator);
REQ(CHILD(n, 0), AT);
REQ(CHILD(n, 2), NEWLINE);

return ast_for_expr(c, CHILD(n, 1));
}

Expand Down
28 changes: 12 additions & 16 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1876,18 +1876,15 @@ get_ref_type(struct compiler *c, PyObject *name)
return CELL;
scope = PyST_GetScope(c->u->u_ste, name);
if (scope == 0) {
char buf[350];
PyOS_snprintf(buf, sizeof(buf),
"unknown scope for %.100s in %.100s(%s)\n"
"symbols: %s\nlocals: %s\nglobals: %s",
PyUnicode_AsUTF8(name),
PyUnicode_AsUTF8(c->u->u_name),
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_id)),
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_symbols)),
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_varnames)),
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_names))
);
Py_FatalError(buf);
_Py_FatalErrorFormat(__func__,
"unknown scope for %.100s in %.100s(%s)\n"
"symbols: %s\nlocals: %s\nglobals: %s",
PyUnicode_AsUTF8(name),
PyUnicode_AsUTF8(c->u->u_name),
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_id)),
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_symbols)),
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_varnames)),
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_names)));
}

return scope;
Expand Down Expand Up @@ -1930,15 +1927,14 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags, Py
else /* (reftype == FREE) */
arg = compiler_lookup_arg(c->u->u_freevars, name);
if (arg == -1) {
fprintf(stderr,
_Py_FatalErrorFormat(__func__,
"lookup %s in %s %d %d\n"
"freevars of %s: %s\n",
PyUnicode_AsUTF8(PyObject_Repr(name)),
PyUnicode_AsUTF8(c->u->u_name),
reftype, arg,
PyUnicode_AsUTF8(co->co_name),
PyUnicode_AsUTF8(PyObject_Repr(co->co_freevars)));
Py_FatalError("compiler_make_closure()");
}
ADDOP_I(c, LOAD_CLOSURE, arg);
}
Expand Down Expand Up @@ -5411,8 +5407,8 @@ stackdepth(struct compiler *c)
struct instr *instr = &b->b_instr[i];
int effect = stack_effect(instr->i_opcode, instr->i_oparg, 0);
if (effect == PY_INVALID_STACK_EFFECT) {
fprintf(stderr, "opcode = %d\n", instr->i_opcode);
Py_FatalError("PyCompile_OpcodeStackEffect()");
_Py_FatalErrorFormat(__func__,
"opcode = %d", instr->i_opcode);
}
int new_depth = depth + effect;
if (new_depth > maxdepth) {
Expand Down
2 changes: 1 addition & 1 deletion Python/frozenmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ Py_FrozenMain(int argc, char **argv)

n = PyImport_ImportFrozenModule("__main__");
if (n == 0)
Py_FatalError("__main__ not frozen");
Py_FatalError("the __main__ module is not frozen");
if (n < 0) {
PyErr_Print();
sts = 1;
Expand Down
6 changes: 3 additions & 3 deletions Python/import.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ _PyImport_ReInitLock(void)
if (import_lock != NULL) {
import_lock = PyThread_allocate_lock();
if (import_lock == NULL) {
Py_FatalError("PyImport_ReInitLock failed to create a new lock");
_Py_FatalErrorFunc(__func__, "failed to create a new lock");
}
}
if (import_lock_level > 1) {
Expand Down Expand Up @@ -310,7 +310,7 @@ PyImport_GetModuleDict(void)
{
PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
if (interp->modules == NULL) {
Py_FatalError("no module dictionary");
Py_FatalError("interpreter has no modules dictionary");
}
return interp->modules;
}
Expand Down Expand Up @@ -982,7 +982,7 @@ PyImport_ExecCodeModuleWithPathnames(const char *name, PyObject *co,
_Py_IDENTIFIER(_get_sourcefile);

if (interp == NULL) {
Py_FatalError("no interpreter!");
Py_FatalError("no current interpreter");
}

external= PyObject_GetAttrString(interp->importlib,
Expand Down
10 changes: 5 additions & 5 deletions Python/mysnprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
}

len = vsprintf(buffer, format, va);
if (len < 0)
if (len < 0) {
/* ignore the error */;

else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");

}
else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE) {
_Py_FatalErrorFunc(__func__, "Buffer overflow");
}
else {
const size_t to_copy = (size_t)len < size ?
(size_t)len : size - 1;
Expand Down
14 changes: 10 additions & 4 deletions Python/pathconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,12 @@ pathconfig_global_init(void)

/* External interface */

static void _Py_NO_RETURN
path_out_of_memory(const char *func)
{
_Py_FatalErrorFunc(func, "out of memory");
}

void
Py_SetPath(const wchar_t *path)
{
Expand Down Expand Up @@ -515,7 +521,7 @@ Py_SetPath(const wchar_t *path)
|| _Py_path_config.exec_prefix == NULL
|| _Py_path_config.module_search_path == NULL)
{
Py_FatalError("out of memory");
path_out_of_memory(__func__);
}
}

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

if (_Py_path_config.home == NULL) {
Py_FatalError("out of memory");
path_out_of_memory(__func__);
}
}

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

if (_Py_path_config.program_name == NULL) {
Py_FatalError("out of memory");
path_out_of_memory(__func__);
}
}

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

if (_Py_path_config.program_full_path == NULL) {
Py_FatalError("out of memory");
path_out_of_memory(__func__);
}
}

Expand Down
Loading