[pypy-commit] pypy reverse-debugger: Breakpoint
arigo
pypy.commits at gmail.com
Mon Jun 20 04:05:45 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: reverse-debugger
Changeset: r85233:29dbfbbe1024
Date: 2016-06-20 10:06 +0200
http://bitbucket.org/pypy/pypy/changeset/29dbfbbe1024/
Log: Breakpoint
diff --git a/rpython/rlib/revdb.py b/rpython/rlib/revdb.py
--- a/rpython/rlib/revdb.py
+++ b/rpython/rlib/revdb.py
@@ -55,6 +55,9 @@
"""
_change_time('f', time_delta, callback)
+def breakpoint(num):
+ llop.revdb_breakpoint(lltype.Void, num)
+
@specialize.argtype(0)
def get_unique_id(x):
"""Returns the creation number of the object 'x'. For objects created
diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -568,6 +568,7 @@
'revdb_stop_point': LLOp(),
'revdb_send_answer': LLOp(),
'revdb_change_time': LLOp(),
+ 'revdb_breakpoint': LLOp(),
'revdb_get_value': LLOp(sideeffects=False),
'revdb_get_unique_id': LLOp(sideeffects=False),
## 'revdb_track_object': LLOp(),
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
@@ -5,10 +5,11 @@
CMD_QUIT = -2
CMD_FORWARD = -3
-ANSWER_INIT = -20
-ANSWER_STD = -21
-ANSWER_FORKED = -22
-ANSWER_AT_END = -23
+ANSWER_INIT = -20
+ANSWER_STD = -21
+ANSWER_FORKED = -22
+ANSWER_AT_END = -23
+ANSWER_BREAKPOINT = -24
class Message(object):
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
@@ -3,6 +3,11 @@
from rpython.translator.revdb.message import *
+class Breakpoint(Exception):
+ def __init__(self, num):
+ self.num = num
+
+
class ReplayProcess(object):
"""Represent one replaying subprocess.
@@ -73,8 +78,18 @@
def forward(self, steps):
"""Move this subprocess forward in time."""
self.send(Message(CMD_FORWARD, steps))
- msg = self.expect(ANSWER_STD, Ellipsis, Ellipsis)
+ #
+ msg = self.recv()
+ if msg.cmd == ANSWER_BREAKPOINT:
+ bkpt_num = msg.arg3
+ msg = self.recv()
+ else:
+ bkpt_num = None
+ assert msg.cmd == ANSWER_STD
self.update_times(msg)
+ #
+ if bkpt_num is not None:
+ raise Breakpoint(bkpt_num)
return msg
@@ -83,7 +98,7 @@
"""
MAX_SUBPROCESSES = 31 # maximum number of subprocesses
STEP_RATIO = 0.25 # subprocess n is between subprocess n-1
- # and the end, at this time fraction
+ # and the end, at this fraction of interval
def __init__(self, executable, revdb_log_filename):
s1, s2 = socket.socketpair()
@@ -120,7 +135,7 @@
next_time = latest_done + int(self.STEP_RATIO * range_not_done) + 1
return next_time
- def forward(self, steps):
+ def go_forward(self, steps):
"""Go forward, for the given number of 'steps' of time.
If needed, it will leave clones at intermediate times.
@@ -151,7 +166,9 @@
def jump_in_time(self, target_time):
"""Jump in time at the given 'target_time'.
- This function can close the active subprocess.
+ This function can close the active subprocess. But you should
+ remove the breakpoints first, in case the same subprocess remains
+ active.
"""
if target_time < 1:
target_time = 1
@@ -161,8 +178,8 @@
cur_time = self.get_current_time()
if target_time >= cur_time: # can go forward
if cur_time >= max(self.paused): # current time is past all forks
- self.forward(target_time - cur_time)
+ self.go_forward(target_time - cur_time)
return
# else, start from a fork
self._resume(max(time for time in self.paused if time <= target_time))
- self.forward(target_time - self.get_current_time())
+ self.go_forward(target_time - self.get_current_time())
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
@@ -196,10 +196,11 @@
#define CMD_QUIT (-2)
#define CMD_FORWARD (-3)
-#define ANSWER_INIT (-20)
-#define ANSWER_STD (-21)
-#define ANSWER_FORKED (-22)
-#define ANSWER_AT_END (-23)
+#define ANSWER_INIT (-20)
+#define ANSWER_STD (-21)
+#define ANSWER_FORKED (-22)
+#define ANSWER_AT_END (-23)
+#define ANSWER_BREAKPOINT (-24)
typedef void (*rpy_revdb_command_fn)(rpy_revdb_command_t *, RPyString *);
@@ -640,27 +641,24 @@
pending_after_forward = callback;
break;
- case 'k': /* breakpoint */
- if (time <= 0) {
- fprintf(stderr, "revdb.breakpoint(): non-positive amount of "
- "steps\n");
- exit(1);
- }
- if (stopped_time != 0) {
- fprintf(stderr, "revdb.breakpoint(): cannot be called from a "
- "debug command\n");
- exit(1);
- }
- rpy_revdb.stop_point_break = rpy_revdb.stop_point_seen + time;
- pending_after_forward = callback;
- break;
-
default:
abort(); /* unreachable */
}
}
RPY_EXTERN
+void rpy_reverse_db_breakpoint(int64_t num)
+{
+ if (stopped_time != 0) {
+ fprintf(stderr, "revdb.breakpoint(): cannot be called from a "
+ "debug command\n");
+ exit(1);
+ }
+ rpy_revdb.stop_point_break = rpy_revdb.stop_point_seen + 1;
+ write_answer(ANSWER_BREAKPOINT, rpy_revdb.stop_point_break, 0, num);
+}
+
+RPY_EXTERN
long long rpy_reverse_db_get_value(char value_id)
{
switch (value_id) {
diff --git a/rpython/translator/revdb/src-revdb/revdb_include.h b/rpython/translator/revdb/src-revdb/revdb_include.h
--- a/rpython/translator/revdb/src-revdb/revdb_include.h
+++ b/rpython/translator/revdb/src-revdb/revdb_include.h
@@ -87,6 +87,9 @@
#define OP_REVDB_CHANGE_TIME(mode, time, callback, r) \
rpy_reverse_db_change_time(mode, time, callback)
+#define OP_REVDB_BREAKPOINT(num, r) \
+ rpy_reverse_db_breakpoint(num)
+
#define OP_REVDB_GET_VALUE(value_id, r) \
r = rpy_reverse_db_get_value(value_id)
@@ -108,6 +111,7 @@
RPY_EXTERN Signed rpy_reverse_db_identityhash(struct pypy_header0 *obj);
RPY_EXTERN void rpy_reverse_db_change_time(char mode, long long time,
void callback(void));
+RPY_EXTERN void rpy_reverse_db_breakpoint(int64_t num);
RPY_EXTERN long long rpy_reverse_db_get_value(char value_id);
RPY_EXTERN uint64_t rpy_reverse_db_unique_id_break(void *new_object);
RPY_EXTERN void rpy_reverse_db_track_object(long long unique_id,
diff --git a/rpython/translator/revdb/test/test_process.py b/rpython/translator/revdb/test/test_process.py
--- a/rpython/translator/revdb/test/test_process.py
+++ b/rpython/translator/revdb/test/test_process.py
@@ -1,6 +1,8 @@
+import py
from rpython.rlib import revdb
+from rpython.rlib.debug import debug_print
from rpython.translator.revdb.message import *
-from rpython.translator.revdb.process import ReplayProcessGroup
+from rpython.translator.revdb.process import ReplayProcessGroup, Breakpoint
from hypothesis import given, strategies
@@ -14,13 +16,24 @@
pass
class DBState:
- pass
+ break_loop = -1
dbstate = DBState()
+ def blip(cmd, extra):
+ debug_print('<<<', cmd.c_cmd, cmd.c_arg1,
+ cmd.c_arg2, cmd.c_arg3, extra, '>>>')
+ if extra == 'set-breakpoint':
+ dbstate.break_loop = cmd.c_arg1
+ revdb.send_answer(42, cmd.c_cmd, -43, -44, extra)
+ lambda_blip = lambda: blip
+
def main(argv):
+ revdb.register_debug_command(1, lambda_blip)
for i, op in enumerate(argv[1:]):
dbstate.stuff = Stuff()
dbstate.stuff.x = i + 1000
+ if dbstate.break_loop == i:
+ revdb.breakpoint(99)
revdb.stop_point()
print op
return 9
@@ -36,7 +49,7 @@
def test_forward(self):
group = ReplayProcessGroup(str(self.exename), self.rdbname)
- group.forward(100)
+ group.go_forward(100)
assert group.get_current_time() == 10
assert sorted(group.paused) == [1, 4, 6, 8, 9, 10]
assert group._check_current_time(10)
@@ -47,3 +60,11 @@
for target_time in target_times:
group.jump_in_time(target_time)
group._check_current_time(target_time)
+
+ def test_breakpoint(self):
+ group = ReplayProcessGroup(str(self.exename), self.rdbname)
+ group.active.send(Message(1, 6, extra='set-breakpoint'))
+ group.active.expect(42, 1, -43, -44, 'set-breakpoint')
+ e = py.test.raises(Breakpoint, group.go_forward, 10)
+ assert e.value.num == 99
+ group._check_current_time(7)
More information about the pypy-commit
mailing list