[pypy-commit] pypy reverse-debugger: Stop using setjmp/longjmp, and instead kill the subprocess. (Previously
arigo
pypy.commits at gmail.com
Fri Aug 5 10:53:48 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: reverse-debugger
Changeset: r86031:cf7c9337178d
Date: 2016-08-05 16:54 +0200
http://bitbucket.org/pypy/pypy/changeset/cf7c9337178d/
Log: Stop using setjmp/longjmp, and instead kill the subprocess.
(Previously the subprocess was in a half-zombie state.)
diff --git a/rpython/translator/revdb/message.py b/rpython/translator/revdb/message.py
--- a/rpython/translator/revdb/message.py
+++ b/rpython/translator/revdb/message.py
@@ -48,6 +48,10 @@
# if breakpoint_mode=='i': ignored, never sent
ANSWER_BREAKPOINT = -24
+# sent after an Attempted to do I/O or access raw memory, as the last message
+ANSWER_ATTEMPT_IO = -25
+
+
# print one line of a file to the console, for CMD_PRINT
# Message(ANSWER_LINECACHE, linenum, extra=filename)
ANSWER_LINECACHE = 19
diff --git a/rpython/translator/revdb/process.py b/rpython/translator/revdb/process.py
--- a/rpython/translator/revdb/process.py
+++ b/rpython/translator/revdb/process.py
@@ -57,6 +57,10 @@
return a
+class RecreateSubprocess(Exception):
+ pass
+
+
class ReplayProcess(object):
"""Represent one replaying subprocess.
@@ -207,6 +211,8 @@
pgroup.all_printed_objects_lst.append(uid)
sys.stdout.write('$%d = ' % nid)
sys.stdout.flush()
+ elif msg.cmd == ANSWER_ATTEMPT_IO:
+ raise RecreateSubprocess
else:
print >> sys.stderr, "unexpected %r" % (msg,)
@@ -441,7 +447,8 @@
def _resume(self, from_time):
clone_me = self.paused[from_time]
- self.active.close()
+ if self.active is not None:
+ self.active.close()
self.active = clone_me.clone()
def jump_in_time(self, target_time):
@@ -534,6 +541,12 @@
self.active.send(Message(CMD_ATTACHID, nid, uid, int(watch_env)))
self.active.expect_ready()
+ def recreate_subprocess(self):
+ # recreate a subprocess at the current time
+ time = self.get_current_time()
+ self.active = None
+ self.jump_in_time(time)
+
def print_cmd(self, expression, nids=[]):
"""Print an expression.
"""
@@ -545,7 +558,10 @@
self.active.tainted = True
self.attach_printed_objects(uids, watch_env=False)
self.active.send(Message(CMD_PRINT, extra=expression))
- self.active.print_text_answer(pgroup=self)
+ try:
+ self.active.print_text_answer(pgroup=self)
+ except RecreateSubprocess:
+ self.recreate_subprocess()
def show_backtrace(self, complete=1):
"""Show the backtrace.
@@ -553,14 +569,20 @@
if complete:
self.active.tainted = True
self.active.send(Message(CMD_BACKTRACE, complete))
- self.active.print_text_answer()
+ try:
+ self.active.print_text_answer()
+ except RecreateSubprocess:
+ self.recreate_subprocess()
def show_locals(self):
"""Show the locals.
"""
self.active.tainted = True
self.active.send(Message(CMD_LOCALS))
- self.active.print_text_answer()
+ try:
+ self.active.print_text_answer()
+ except RecreateSubprocess:
+ self.recreate_subprocess()
def edit_breakpoints(self):
return self.all_breakpoints
diff --git a/rpython/translator/revdb/src-revdb/revdb.c b/rpython/translator/revdb/src-revdb/revdb.c
--- a/rpython/translator/revdb/src-revdb/revdb.c
+++ b/rpython/translator/revdb/src-revdb/revdb.c
@@ -9,7 +9,6 @@
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
-#include <setjmp.h>
#include <signal.h>
#include <search.h>
@@ -38,7 +37,7 @@
#define FID_REGULAR_MODE 'R'
#define FID_SAVED_STATE 'S'
-#define FID_JMPBUF_PROTECTED 'J'
+#define FID_POTENTIAL_IO 'I'
typedef struct {
@@ -566,6 +565,7 @@
#define ANSWER_FORKED (-22)
#define ANSWER_AT_END (-23)
#define ANSWER_BREAKPOINT (-24)
+#define ANSWER_ATTEMPT_IO (-25)
#define RECORD_BKPT_NUM 50
@@ -575,7 +575,6 @@
static const char *rpy_rev_filename;
static uint64_t interactive_break = 1, finalizer_break = -1, uid_break = -1;
static uint64_t total_stop_points;
-static jmp_buf jmp_buf_cancel_execution;
static void (*pending_after_forward)(void);
static RPyString *empty_string;
static uint64_t last_recorded_breakpoint_loc;
@@ -858,13 +857,12 @@
*/
fprintf(stderr, "%s:%d: Attempted to do I/O or access raw memory\n",
file, line);
- if (flag_io_disabled == FID_JMPBUF_PROTECTED) {
- longjmp(jmp_buf_cancel_execution, 1);
- }
- else {
+ if (flag_io_disabled != FID_POTENTIAL_IO) {
fprintf(stderr, "but we are not in a jmpbuf_protected section\n");
exit(1);
}
+ write_answer(ANSWER_ATTEMPT_IO, 0, 0, 0);
+ exit(0);
}
}
@@ -916,23 +914,24 @@
set_revdb_breakpoints();
}
-static void protect_jmpbuf(void)
+static void protect_potential_io(void)
{
- change_flag_io_disabled(FID_SAVED_STATE, FID_JMPBUF_PROTECTED);
+ change_flag_io_disabled(FID_SAVED_STATE, FID_POTENTIAL_IO);
saved_exc[0] = pypy_g_ExcData.ed_exc_type;
saved_exc[1] = pypy_g_ExcData.ed_exc_value;
pypy_g_ExcData.ed_exc_type = NULL;
pypy_g_ExcData.ed_exc_value = NULL;
}
-static void unprotect_jmpbuf(void)
+static void unprotect_potential_io(void)
{
- change_flag_io_disabled(FID_JMPBUF_PROTECTED, FID_SAVED_STATE);
+ change_flag_io_disabled(FID_POTENTIAL_IO, FID_SAVED_STATE);
if (pypy_g_ExcData.ed_exc_type != NULL) {
fprintf(stderr, "Command crashed with %.*s\n",
(int)(pypy_g_ExcData.ed_exc_type->ov_name->rs_chars.length),
pypy_g_ExcData.ed_exc_type->ov_name->rs_chars.items);
- exit(1);
+ write_answer(ANSWER_ATTEMPT_IO, 1, 0, 0);
+ exit(0);
}
pypy_g_ExcData.ed_exc_type = saved_exc[0];
pypy_g_ExcData.ed_exc_value = saved_exc[1];
@@ -942,10 +941,9 @@
rpy_revdb_command_t *cmd,
RPyString *extra)
{
- protect_jmpbuf();
- if (setjmp(jmp_buf_cancel_execution) == 0)
- func(cmd, extra);
- unprotect_jmpbuf();
+ protect_potential_io();
+ func(cmd, extra);
+ unprotect_potential_io();
}
static void check_at_end(uint64_t stop_points)
@@ -1267,10 +1265,9 @@
save_state();
if (rpy_revdb_commands.rp_alloc) {
- protect_jmpbuf();
- if (setjmp(jmp_buf_cancel_execution) == 0)
- rpy_revdb_commands.rp_alloc(uid, new_object);
- unprotect_jmpbuf();
+ protect_potential_io();
+ rpy_revdb_commands.rp_alloc(uid, new_object);
+ unprotect_potential_io();
}
uid_break = *++future_next_id;
restore_state();
diff --git a/rpython/translator/revdb/test/test_basic.py b/rpython/translator/revdb/test/test_basic.py
--- a/rpython/translator/revdb/test/test_basic.py
+++ b/rpython/translator/revdb/test/test_basic.py
@@ -395,6 +395,7 @@
def test_io_not_permitted(self):
child = self.replay(stderr=subprocess.PIPE)
child.send(Message(1, extra='oops'))
+ child.expect(ANSWER_ATTEMPT_IO)
child.close()
err = self.subproc.stderr.read()
assert err.endswith(': Attempted to do I/O or access raw memory\n')
More information about the pypy-commit
mailing list