[pypy-commit] pypy reverse-debugger: Can't do I/O in rpython commands

arigo pypy.commits at gmail.com
Sat Jun 11 04:47:45 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: reverse-debugger
Changeset: r85094:44e6fa91e646
Date: 2016-06-11 10:48 +0200
http://bitbucket.org/pypy/pypy/changeset/44e6fa91e646/

Log:	Can't do I/O in rpython commands

diff --git a/rpython/translator/revdb/rdb-src/revdb.c b/rpython/translator/revdb/rdb-src/revdb.c
--- a/rpython/translator/revdb/rdb-src/revdb.c
+++ b/rpython/translator/revdb/rdb-src/revdb.c
@@ -6,6 +6,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <ctype.h>
+#include <setjmp.h>
 
 #include "preimpl.h"
 #include "structdef.h"
@@ -189,6 +190,8 @@
 enum { PK_MAIN_PROCESS, PK_FROZEN_PROCESS, PK_DEBUG_PROCESS };
 static unsigned char process_kind = PK_MAIN_PROCESS;
 static unsigned char flag_exit_run_debug_process;
+static unsigned char flag_executing_rpython_code;
+static jmp_buf jmp_buf_cancel_execution;
 static uint64_t latest_fork;
 
 static uint64_t total_stop_points;
@@ -284,15 +287,39 @@
 RPY_EXTERN
 char *rpy_reverse_db_fetch(int expected_size)
 {
-    ssize_t rsize, keep = rpy_revdb.buf_limit - 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 (!flag_executing_rpython_code) {
+        ssize_t rsize, keep = rpy_revdb.buf_limit - 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;
+    }
+    else {
+        /* this is called when we are in execute_rpy_command(): we are
+           running some custom code now, and we can't just perform I/O
+           or access raw memory---because there is no raw memory! 
+        */
+        printf("Attempted to do I/O or access raw memory\n");
+        longjmp(jmp_buf_cancel_execution, 1);
+    }
+}
+
+static void disable_io(rpy_revdb_t *dinfo)
+{
+    *dinfo = rpy_revdb;   /* save the complete struct */
+    rpy_revdb.buf_p = NULL;
+    rpy_revdb.buf_limit = NULL;
+    flag_executing_rpython_code = 1;
+}
+
+static void enable_io(rpy_revdb_t *dinfo)
+{
+    flag_executing_rpython_code = 0;
+    rpy_revdb = *dinfo;
 }
 
 /* generated by RPython */
@@ -303,6 +330,7 @@
 {
     size_t length = strlen(arguments);
     RPyString *s;
+    rpy_revdb_t dinfo;
 
     while (length > 0 && isspace(arguments[length - 1]))
         length--;
@@ -316,7 +344,10 @@
     RPyString_Size(s) = length;
     memcpy(_RPyString_AsString(s), arguments, length);
 
-    rpy_revdb_command_funcs[index](s);
+    disable_io(&dinfo);
+    if (setjmp(jmp_buf_cancel_execution) == 0)
+        rpy_revdb_command_funcs[index](s);
+    enable_io(&dinfo);
 }
 
 struct action_s {
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
@@ -189,6 +189,9 @@
         #
         def blip(cmdline):
             revdb.send_output('<<<' + cmdline + '>>>\n')
+            if cmdline == 'oops':
+                for i in range(1000):
+                    print 42     # I/O not permitted
             revdb.send_output('blipped\n')
         lambda_blip = lambda: blip
         #
@@ -207,3 +210,22 @@
         child.sendline('r  foo  bar  baz  ')
         child.expectx('<<<foo  bar  baz>>>\r\nblipped\r\n')
         child.expectx('(3)$ ')
+
+    def test_io_not_permitted(self):
+        child = self.replay()
+        child.expectx('(3)$ ')
+        child.sendline('r oops')
+        child.expectx('<<<oops>>>\r\nAttempted to do I/O or access raw memory')
+        child.expectx('(3)$ ')
+
+    def test_interaction_with_forward(self):
+        child = self.replay()
+        child.expectx('(3)$ ')
+        child.sendline('go 1')
+        child.expectx('(1)$ ')
+        child.sendline('r oops')
+        child.expectx('<<<oops>>>\r\nAttempted to do I/O or access raw memory')
+        child.expectx('(1)$ ')
+        child.sendline('forward 50')
+        child.expectx('At end.\r\n')
+        child.expectx('(3)$ ')


More information about the pypy-commit mailing list