Author: Armin Rigo <[email protected]>
Branch: reverse-debugger
Changeset: r85393:6e38ff9d8113
Date: 2016-06-27 11:06 +0200
http://bitbucket.org/pypy/pypy/changeset/6e38ff9d8113/
Log: Start to work on finalizers: split the log file into packets
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
@@ -1,6 +1,7 @@
#include "common_header.h"
#include <stdlib.h>
#include <stdio.h>
+#include <stddef.h>
#include <string.h>
#include <assert.h>
#include <sys/stat.h>
@@ -24,17 +25,19 @@
#define WEAKREF_AFTERWARDS_DEAD ((char)0xf2)
#define WEAKREF_AFTERWARDS_ALIVE ((char)0xeb)
+//#define ASYNC_FINALIZER ((int16_t)0xff46)
+
typedef struct {
Signed version;
- Signed reserved1, reserved2;
+ uint64_t reserved1, reserved2;
int argc;
char **argv;
} rdb_header_t;
rpy_revdb_t rpy_revdb;
-static char rpy_rev_buffer[16384];
+static char rpy_rev_buffer[16384]; /* max. 32768 */
static int rpy_rev_fileno = -1;
static unsigned char flag_io_disabled;
@@ -109,9 +112,6 @@
int i;
assert(RPY_RDB_REPLAY == 0);
- rpy_revdb.buf_p = rpy_rev_buffer;
- rpy_revdb.buf_limit = rpy_rev_buffer + sizeof(rpy_rev_buffer) - 32;
- rpy_revdb.unique_id_seen = 1;
if (filename && *filename) {
putenv("PYPYRDB=");
@@ -137,20 +137,29 @@
h.argv = argv;
write_all((const char *)&h, sizeof(h));
}
+ rpy_revdb.buf_p = rpy_rev_buffer + sizeof(int16_t);
+ rpy_revdb.buf_limit = rpy_rev_buffer + sizeof(rpy_rev_buffer) - 32;
+ rpy_revdb.unique_id_seen = 1;
+}
+
+static void flush_buffer(void)
+{
+ /* write the current buffer content to the OS */
+ ssize_t size = rpy_revdb.buf_p - rpy_rev_buffer;
+ rpy_revdb.buf_p = rpy_rev_buffer + sizeof(int16_t);
+ if (rpy_rev_fileno >= 0)
+ write_all(rpy_rev_buffer, size);
}
RPY_EXTERN
void rpy_reverse_db_flush(void)
{
- /* write the current buffer content to the OS */
-
- ssize_t wsize, size = rpy_revdb.buf_p - rpy_rev_buffer;
- char *p;
- rpy_revdb.buf_p = rpy_rev_buffer;
- if (size == 0 || rpy_rev_fileno < 0)
- return;
-
- write_all(rpy_rev_buffer, size);
+ ssize_t packet_size = rpy_revdb.buf_p - (rpy_rev_buffer + sizeof(int16_t));
+ if (packet_size != 0) {
+ assert(0 < packet_size && packet_size <= 32767);
+ *(int16_t *)rpy_rev_buffer = packet_size;
+ flush_buffer();
+ }
}
RPY_EXTERN
@@ -176,7 +185,7 @@
return obj->h_hash;
}
-static int64_t recording_offset(void)
+static uint64_t recording_offset(void)
{
off_t base_offset;
ssize_t extra_size = rpy_revdb.buf_p - rpy_rev_buffer;
@@ -516,6 +525,7 @@
rpy_revdb.buf_p = rpy_rev_buffer;
rpy_revdb.buf_limit = rpy_rev_buffer;
+ rpy_revdb.buf_readend = rpy_rev_buffer;
rpy_revdb.stop_point_break = 1;
rpy_revdb.unique_id_seen = 1;
@@ -528,19 +538,44 @@
signal(SIGCHLD, SIG_IGN);
}
+static void fetch_more(ssize_t keep, ssize_t expected_size)
+{
+ ssize_t rsize;
+ if (rpy_revdb.buf_p != rpy_rev_buffer)
+ memmove(rpy_rev_buffer, rpy_revdb.buf_p, keep);
+ rsize = read_at_least(rpy_rev_buffer + keep,
+ expected_size - keep,
+ sizeof(rpy_rev_buffer) - keep);
+ rpy_revdb.buf_p = rpy_rev_buffer;
+ rpy_revdb.buf_readend = rpy_rev_buffer + keep + rsize;
+ /* rpy_revdb.buf_limit is not set */
+}
+
RPY_EXTERN
-char *rpy_reverse_db_fetch(int expected_size, const char *file, int line)
+char *rpy_reverse_db_fetch(const char *file, int line)
{
if (!flag_io_disabled) {
- ssize_t rsize, keep = rpy_revdb.buf_limit - rpy_revdb.buf_p;
+ ssize_t keep;
+ ssize_t full_packet_size;
+ if (rpy_revdb.buf_limit != rpy_revdb.buf_p) {
+ fprintf(stderr, "bad log format: incomplete packet\n");
+ exit(1);
+ }
+ keep = rpy_revdb.buf_readend - rpy_revdb.buf_p;
assert(keep >= 0);
- memmove(rpy_rev_buffer, rpy_revdb.buf_p, keep);
- rsize = read_at_least(rpy_rev_buffer + keep,
- expected_size - keep,
- sizeof(rpy_rev_buffer) - keep);
- rpy_revdb.buf_p = rpy_rev_buffer;
- rpy_revdb.buf_limit = rpy_rev_buffer + keep + rsize;
- return rpy_rev_buffer;
+
+ if (keep < sizeof(int16_t)) {
+ /* 'keep' does not even contain the next packet header */
+ fetch_more(keep, sizeof(int16_t));
+ keep = rpy_revdb.buf_readend - rpy_rev_buffer;
+ }
+ full_packet_size = sizeof(int16_t) + *(int16_t *)rpy_revdb.buf_p;
+ if (keep < full_packet_size) {
+ fetch_more(keep, full_packet_size);
+ }
+ rpy_revdb.buf_limit = rpy_revdb.buf_p + full_packet_size;
+ rpy_revdb.buf_p += sizeof(int16_t);
+ return rpy_revdb.buf_p;
}
else {
/* this is called when we are in execute_rpy_command(): we are
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
@@ -16,7 +16,7 @@
#define RPY_RDB_DYNAMIC_REPLAY
#endif
bool_t watch_enabled;
- char *buf_p, *buf_limit;
+ char *buf_p, *buf_limit, *buf_readend;
uint64_t stop_point_seen, stop_point_break;
uint64_t unique_id_seen, unique_id_break;
} rpy_revdb_t;
@@ -53,8 +53,7 @@
char *_src = rpy_revdb.buf_p; \
char *_end1 = _src + sizeof(_e); \
if (_end1 > rpy_revdb.buf_limit) { \
- _src = rpy_reverse_db_fetch(sizeof(_e), \
- __FILE__, __LINE__); \
+ _src = rpy_reverse_db_fetch(__FILE__, __LINE__); \
_end1 = _src + sizeof(_e); \
} \
rpy_revdb.buf_p = _end1; \
@@ -114,8 +113,7 @@
r = rpy_reverse_db_weakref_deref(weakref)
RPY_EXTERN void rpy_reverse_db_flush(void);
-RPY_EXTERN char *rpy_reverse_db_fetch(int expected_size,
- const char *file, int line);
+RPY_EXTERN char *rpy_reverse_db_fetch(const char *file, int line);
RPY_EXTERN void rpy_reverse_db_stop_point(void);
RPY_EXTERN void rpy_reverse_db_send_answer(int cmd, int64_t arg1, int64_t arg2,
int64_t arg3, RPyString *extra);
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
@@ -21,19 +21,29 @@
assert header == 'RevDB:\t' + '\t'.join(expected_argv) + '\n'
#
self.cur = 0
- x = self.next('c'); assert x == '\x00'
- x = self.next(); assert x == 0x00FF0001
- x = self.next(); assert x == 0
- x = self.next(); assert x == 0
- self.argc = self.next()
- self.argv = self.next()
+ x = self.read1('c'); assert x == '\x00'
+ x = self.read1('P'); assert x == 0x00FF0001
+ x = self.read1('P'); assert x == 0
+ x = self.read1('P'); assert x == 0
+ self.argc = self.read1('P')
+ self.argv = self.read1('P')
+ self.current_packet_end = self.cur
self.read_check_argv(expected_argv)
- def next(self, mode='P'):
+ def read1(self, mode):
p = self.cur
self.cur = p + struct.calcsize(mode)
return struct.unpack_from(mode, self.buffer, p)[0]
+ def next(self, mode='P'):
+ if self.current_packet_end == self.cur:
+ packet_size = self.read1('h')
+ assert packet_size > 0
+ self.current_packet_end = self.cur + packet_size
+ result = self.read1(mode)
+ assert self.cur <= self.current_packet_end
+ return result
+
def read_check_argv(self, expected):
assert self.argc == len(expected)
for i in range(self.argc):
diff --git a/rpython/translator/revdb/test/test_weak.py
b/rpython/translator/revdb/test/test_weak.py
--- a/rpython/translator/revdb/test/test_weak.py
+++ b/rpython/translator/revdb/test/test_weak.py
@@ -1,5 +1,5 @@
-import weakref, gc
-from rpython.rlib import revdb
+import weakref
+from rpython.rlib import revdb, rgc
from rpython.rlib.debug import debug_print
from rpython.rlib.objectmodel import keepalive_until_here
from rpython.translator.revdb.message import *
@@ -23,7 +23,7 @@
WEAKREF_AFTERWARDS_ALIVE = chr(0xeb)
-class TestRecordingWeakref(BaseRecordingTests):
+class TestRecording(BaseRecordingTests):
def test_weakref_create(self):
class X:
@@ -71,8 +71,25 @@
x = rdb.next('q'); assert x == 0 # number of stop points
assert rdb.done()
+ def test_finalizer_light_ignored(self):
+ class X:
+ @rgc.must_be_light_finalizer
+ def __del__(self):
+ pass
+ def main(argv):
+ lst = [X() for i in range(3000)]
+ for i in range(3000):
+ lst[i] = None
+ revdb.stop_point()
+ return 9
+ self.compile(main, [], backendopt=False)
+ out = self.run('Xx')
+ rdb = self.fetch_rdb([self.exename, 'Xx'])
+ x = rdb.next('q'); assert x == 3000 # number of stop points
+ assert rdb.done()
-class TestReplayingWeakref(InteractiveTests):
+
+class TestReplaying(InteractiveTests):
expected_stop_points = 1
def setup_class(cls):
@@ -108,7 +125,7 @@
print ''.join(outp)
if (j % 1000) == 999:
debug_print('============= COLLECT ===========')
- gc.collect()
+ rgc.collect()
debug_print('------ done', j, '.')
assert not dead[0]
assert not dead[-1]
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit