Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
a9a9dab0
Kaydet (Commit)
a9a9dab0
authored
Tem 13, 2011
tarafından
Victor Stinner
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #12550: Add chain optional argument to faulthandler.register()
Call the previous signal handler if chain is True.
üst
d93da2b9
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
90 additions
and
37 deletions
+90
-37
faulthandler.rst
Doc/library/faulthandler.rst
+2
-2
test_faulthandler.py
Lib/test/test_faulthandler.py
+28
-3
faulthandler.c
Modules/faulthandler.c
+60
-32
No files found.
Doc/library/faulthandler.rst
Dosyayı görüntüle @
a9a9dab0
...
...
@@ -92,11 +92,11 @@ Dump the tracebacks after a timeout
Dump the traceback on a user signal
-----------------------------------
.. function:: register(signum, file=sys.stderr, all_threads=True)
.. function:: register(signum, file=sys.stderr, all_threads=True
, chain=False
)
Register a user signal: install a handler for the *signum* signal to dump
the traceback of all threads, or of the current thread if *all_threads* is
``False``, into *file*.
``False``, into *file*.
Call the previous handler if chain is ``True``.
Not available on Windows.
...
...
Lib/test/test_faulthandler.py
Dosyayı görüntüle @
a9a9dab0
...
...
@@ -452,11 +452,13 @@ if file is not None:
@unittest.skipIf
(
not
hasattr
(
faulthandler
,
"register"
),
"need faulthandler.register"
)
def
check_register
(
self
,
filename
=
False
,
all_threads
=
False
,
unregister
=
False
):
unregister
=
False
,
chain
=
False
):
"""
Register a handler displaying the traceback on a user signal. Raise the
signal and check the written traceback.
If chain is True, check that the previous signal handler is called.
Raise an error if the output doesn't match the expected format.
"""
signum
=
signal
.
SIGUSR1
...
...
@@ -464,22 +466,41 @@ if file is not None:
import faulthandler
import os
import signal
import sys
def func(signum):
os.kill(os.getpid(), signum)
def handler(signum, frame):
handler.called = True
handler.called = False
exitcode = 0
signum = {signum}
unregister = {unregister}
chain = {chain}
if {has_filename}:
file = open({filename}, "wb")
else:
file = None
faulthandler.register(signum, file=file, all_threads={all_threads})
if chain:
signal.signal(signum, handler)
faulthandler.register(signum, file=file,
all_threads={all_threads}, chain={chain})
if unregister:
faulthandler.unregister(signum)
func(signum)
if chain and not handler.called:
if file is not None:
output = file
else:
output = sys.stderr
print("Error: signal handler not called!", file=output)
exitcode = 1
if file is not None:
file.close()
sys.exit(exitcode)
"""
.
strip
()
code
=
code
.
format
(
filename
=
repr
(
filename
),
...
...
@@ -487,6 +508,7 @@ if file is not None:
all_threads
=
all_threads
,
signum
=
signum
,
unregister
=
unregister
,
chain
=
chain
,
)
trace
,
exitcode
=
self
.
get_output
(
code
,
filename
)
trace
=
'
\n
'
.
join
(
trace
)
...
...
@@ -495,7 +517,7 @@ if file is not None:
regex
=
'Current thread XXX:
\n
'
else
:
regex
=
'Traceback
\
(most recent call first
\
):
\n
'
regex
=
expected_traceback
(
6
,
17
,
regex
)
regex
=
expected_traceback
(
7
,
28
,
regex
)
self
.
assertRegex
(
trace
,
regex
)
else
:
self
.
assertEqual
(
trace
,
''
)
...
...
@@ -517,6 +539,9 @@ if file is not None:
def
test_register_threads
(
self
):
self
.
check_register
(
all_threads
=
True
)
def
test_register_chain
(
self
):
self
.
check_register
(
chain
=
True
)
def
test_main
():
support
.
run_unittest
(
FaultHandlerTests
)
...
...
Modules/faulthandler.c
Dosyayı görüntüle @
a9a9dab0
...
...
@@ -8,7 +8,6 @@
#include <pthread.h>
#endif
/* Allocate at maximum 100 MB of the stack to raise the stack overflow */
#define STACK_OVERFLOW_MAX_SIZE (100*1024*1024)
...
...
@@ -72,6 +71,7 @@ typedef struct {
PyObject
*
file
;
int
fd
;
int
all_threads
;
int
chain
;
_Py_sighandler_t
previous
;
PyInterpreterState
*
interp
;
}
user_signal_t
;
...
...
@@ -94,6 +94,7 @@ static user_signal_t *user_signals;
# endif
#endif
static
void
faulthandler_user
(
int
signum
);
#endif
/* FAULTHANDLER_USER */
...
...
@@ -259,9 +260,9 @@ faulthandler_fatal_error(int signum)
/* restore the previous handler */
#ifdef HAVE_SIGACTION
(
void
)
sigaction
(
handler
->
signum
,
&
handler
->
previous
,
NULL
);
(
void
)
sigaction
(
signum
,
&
handler
->
previous
,
NULL
);
#else
(
void
)
signal
(
handler
->
signum
,
handler
->
previous
);
(
void
)
signal
(
signum
,
handler
->
previous
);
#endif
handler
->
enabled
=
0
;
...
...
@@ -587,6 +588,39 @@ faulthandler_cancel_dump_tracebacks_later_py(PyObject *self)
#endif
/* FAULTHANDLER_LATER */
#ifdef FAULTHANDLER_USER
static
int
faulthandler_register
(
int
signum
,
int
chain
,
_Py_sighandler_t
*
p_previous
)
{
#ifdef HAVE_SIGACTION
struct
sigaction
action
;
action
.
sa_handler
=
faulthandler_user
;
sigemptyset
(
&
action
.
sa_mask
);
/* if the signal is received while the kernel is executing a system
call, try to restart the system call instead of interrupting it and
return EINTR. */
action
.
sa_flags
=
SA_RESTART
;
if
(
chain
)
{
/* do not prevent the signal from being received from within its
own signal handler */
action
.
sa_flags
=
SA_NODEFER
;
}
#ifdef HAVE_SIGALTSTACK
if
(
stack
.
ss_sp
!=
NULL
)
{
/* Call the signal handler on an alternate signal stack
provided by sigaltstack() */
action
.
sa_flags
|=
SA_ONSTACK
;
}
#endif
return
sigaction
(
signum
,
&
action
,
p_previous
);
#else
_Py_sighandler_t
previous
;
previous
=
signal
(
signum
,
faulthandler_user
);
if
(
p_previous
!=
NULL
)
*
p_previous
=
previous
;
return
(
previous
==
SIG_ERR
);
#endif
}
/* Handler of user signals (e.g. SIGUSR1).
Dump the traceback of the current thread, or of all threads if
...
...
@@ -621,6 +655,19 @@ faulthandler_user(int signum)
return
;
_Py_DumpTraceback
(
user
->
fd
,
tstate
);
}
#ifdef HAVE_SIGACTION
if
(
user
->
chain
)
{
(
void
)
sigaction
(
signum
,
&
user
->
previous
,
NULL
);
/* call the previous signal handler */
raise
(
signum
);
(
void
)
faulthandler_register
(
signum
,
user
->
chain
,
NULL
);
}
#else
if
(
user
->
chain
)
{
/* call the previous signal handler */
user
->
previous
(
signum
);
}
#endif
errno
=
save_errno
;
}
...
...
@@ -646,25 +693,23 @@ check_signum(int signum)
}
static
PyObject
*
faulthandler_register
(
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kwargs
)
faulthandler_register
_py
(
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kwargs
)
{
static
char
*
kwlist
[]
=
{
"signum"
,
"file"
,
"all_threads"
,
NULL
};
static
char
*
kwlist
[]
=
{
"signum"
,
"file"
,
"all_threads"
,
"chain"
,
NULL
};
int
signum
;
PyObject
*
file
=
NULL
;
int
all_threads
=
1
;
int
chain
=
0
;
int
fd
;
user_signal_t
*
user
;
_Py_sighandler_t
previous
;
#ifdef HAVE_SIGACTION
struct
sigaction
action
;
#endif
PyThreadState
*
tstate
;
int
err
;
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwargs
,
"i|Oi:register"
,
kwlist
,
&
signum
,
&
file
,
&
all_threads
))
"i|Oi
i
:register"
,
kwlist
,
&
signum
,
&
file
,
&
all_threads
,
&
chain
))
return
NULL
;
if
(
!
check_signum
(
signum
))
...
...
@@ -686,25 +731,7 @@ faulthandler_register(PyObject *self,
user
=
&
user_signals
[
signum
];
if
(
!
user
->
enabled
)
{
#ifdef HAVE_SIGACTION
action
.
sa_handler
=
faulthandler_user
;
sigemptyset
(
&
action
.
sa_mask
);
/* if the signal is received while the kernel is executing a system
call, try to restart the system call instead of interrupting it and
return EINTR */
action
.
sa_flags
=
SA_RESTART
;
#ifdef HAVE_SIGALTSTACK
if
(
stack
.
ss_sp
!=
NULL
)
{
/* Call the signal handler on an alternate signal stack
provided by sigaltstack() */
action
.
sa_flags
|=
SA_ONSTACK
;
}
#endif
err
=
sigaction
(
signum
,
&
action
,
&
previous
);
#else
previous
=
signal
(
signum
,
faulthandler_user
);
err
=
(
previous
==
SIG_ERR
);
#endif
err
=
faulthandler_register
(
signum
,
chain
,
&
previous
);
if
(
err
)
{
PyErr_SetFromErrno
(
PyExc_OSError
);
return
NULL
;
...
...
@@ -716,6 +743,7 @@ faulthandler_register(PyObject *self,
user
->
file
=
file
;
user
->
fd
=
fd
;
user
->
all_threads
=
all_threads
;
user
->
chain
=
chain
;
user
->
previous
=
previous
;
user
->
interp
=
tstate
->
interp
;
user
->
enabled
=
1
;
...
...
@@ -947,8 +975,8 @@ static PyMethodDef module_methods[] = {
#ifdef FAULTHANDLER_USER
{
"register"
,
(
PyCFunction
)
faulthandler_register
,
METH_VARARGS
|
METH_KEYWORDS
,
PyDoc_STR
(
"register(signum, file=sys.stderr, all_threads=True): "
(
PyCFunction
)
faulthandler_register
_py
,
METH_VARARGS
|
METH_KEYWORDS
,
PyDoc_STR
(
"register(signum, file=sys.stderr, all_threads=True
, chain=False
): "
"register an handler for the signal 'signum': dump the "
"traceback of the current thread, or of all threads if "
"all_threads is True, into file"
)},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment