Author: Armin Rigo <ar...@tunes.org> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit