Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Control-C isn't handled in all cases #1722

Closed
dhylands opened this issue Dec 15, 2015 · 43 comments
Closed

Control-C isn't handled in all cases #1722

dhylands opened this issue Dec 15, 2015 · 43 comments

Comments

@dhylands
Copy link
Contributor

This was raised over here: http://forum.micropython.org/viewtopic.php?p=7566#p7566

A very specific patch that addresses that particular issue (very narrowly) would be something like this (patching unix/file.c):

@@ -71,7 +71,14 @@ STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
     check_fd_is_open(o);
     mp_int_t r = read(o->fd, buf, size);
     if (r == -1) {
-        *errcode = errno;
+        if (errno == EINTR && MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) {
+            // User pressed Control-C. We return no bytes read so that the
+            // vm will get around to checking mp_pending_exception and raising
+            // a KeyboardInterrupt
+
+            return 0;
+        }
+        *errcode = errno; 
         return MP_STREAM_ERROR;
     }
     return r;

I think that every system call needs something like this in order to have Control-C throw a KeyboardInterrupt rather than some other error (OSError 4 in the above example).

The if check probably best belongs in a macro or function (to improve readability and/or to minimize code size increase), but I figured the issue probably warranted further discussion, so I just posted the patch above rather than creating a PR which I knew would need to be closed.

@pfalcon
Copy link
Contributor

pfalcon commented Dec 15, 2015

So what's being reported here? Segfault on Ctrl+C? High-priority, need more info, there should be links to existing reports (we have 2). One exception thrown instead of another? Lower priority. We discussed similar issue recently, should be linked.

Generally, original reporters should be motivated to submit proper bugreport, and do it well - provide info, describe issue clearly.

@dhylands
Copy link
Contributor Author

I didn't hit a segfault. What happened for me was this:

2071 >./micropython 
MicroPython v1.5.1-116-g8fb255d on 2015-12-15; linux version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>> import sys
>>> sys.stdin.read(1)
^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: 4
>>> sys.stdin.read(1)
^Cdhylands@dave-w520 ~/micropython/micropython/unix  (master)

i.e. the second time I run sys.stdin.read(1) and hit Control-C micropython exited entirely.

I think that this happens because the mp_pending_exception never got cleared due to the OSError exception being raised instead. This was confirmed by doing something else after the first read:

2072 >./micropython 
MicroPython v1.5.1-116-g8fb255d on 2015-12-15; linux version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>> import sys
>>> sys.stdin.read(1)
^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: 4
>>> for i in range(10):
...  print(i)
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyboardInterrupt: 
>>>

So when it entered the for loop, it finally noticed that mp_pending_exception was set and then finally raised the KeyboardInterrupt. So in the second example, I only pressed Control-C once, during the sys.stdin.read(1).

@hosaka
Copy link
Contributor

hosaka commented Dec 16, 2015

In addition to Daves cases I also get the following, by pressing Return right after the first Ctrl-C, seemingly random:

% ./micropython                                                                                                                                        
MicroPython v1.5-297-gf2ed736 on 2015-12-15; linux version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>> import sys
>>> sys.stdin.read(1)
^C 
'\n'
KeyboardInterrupt:
>>> 

@robert-hh
Copy link
Contributor

The reaction to Ctrl-C during read is different, depending on the environment and the version used. I got:

  • Segmentation fault (32 Bit Mint Linux 17.2)
  • Out of memory fault, trying to allocate 2xxxyyy Bytes (62 Bit debian) or also
  • OS Error 4 (64 Bit debian 8)
  • Simple terminating micropython (Windows version)

Running micropython with gdb on 32 bit Mint linux results in:

Program received signal SIGINT, Interrupt.
0xb7fdbd22 in __kernel_vsyscall ()

with the followin stack trace:

(gdb) bt
#0 0xb7fdbd22 in __kernel_vsyscall ()
#1 0xb7e9bbf3 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
#2 0x08072b91 in ?? ()
#3 0x0806984d in ?? ()
#4 0x08060885 in ?? ()
#5 0x0805b2f1 in ?? ()
#6 0x0806d730 in ?? ()
#7 0x08060981 in ?? ()
#8 0x0805b220 in ?? ()
#9 0x0807240e in ?? ()
#10 0x0804a645 in ?? ()
#11 0xb7ddaa83 in __libc_start_main (main=0x8049dec, argc=1, argv=0xbffff204, init=0x8075450,
fini=0x80754c0, rtld_fini=0xb7fed180 <_dl_fini>, stack_end=0xbffff1fc) at libc-start.c:287
#12 0x0804a6ea in ?? ()

@robert-hh
Copy link
Contributor

ctd.: Running under gdb seems more stable. If I enter the gdb command 'c' after getting the gdb prompt follwing Ctrl-C, micropython continues normally. So it might be that by default the signal handler is not set properly, or the default signal handler is at fault..

@dpgeorge
Copy link
Member

Checking for pending exceptions was supposed to be fixed by 5ae3ddc, but that patch only checks if there were no exceptions raised (whereas the issue at hand has one exception being raised, while also the pending exception being set). Well, it certainly needs a proper solution.

@pfalcon
Copy link
Contributor

pfalcon commented Dec 16, 2015

@robert-hh : Thanks for details. Please rebuild on your 32-bit system using "make DEBUG=1 -B", and run that under gdb, and post stacktrace for that.

@pfalcon
Copy link
Contributor

pfalcon commented Dec 16, 2015

Let's concentrate here on resolving long-standing issue of segfault on Ctrl+C on 32-bit x86. Previously, I could not reproduce it under gdb.

Regarding Ctrl+C handling in general, previous discussion on that happened in #1667, so should continue from there.

@robert-hh
Copy link
Contributor

Ctd # 2: I'll make the try with debug enabled, but meanwhile I made the following attemt, by providing a signal handler, which seemed to work:

def signal_handler(signal, frame):
... return True
...
signal.signal(signal.SIGINT, signal_handler)
134685964
sys.stdin.read(1)
^C''
KeyboardInterrupt:

@robert-hh
Copy link
Contributor

OK. Here's the stack trace:

sys.stdin.read(1)
^C
Program received signal SIGINT, Interrupt.
0xb7fdbd22 in __kernel_vsyscall ()
(gdb) bt
#0 0xb7fdbd22 in __kernel_vsyscall ()
#1 0xb7e9bbf3 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
#2 0x0808b3d1 in fdfile_read (o_in=0x809dcc8 <mp_sys_stdin_obj>, buf=0xb7cc5500, size=1,
errcode=0xbfffdd68) at file.c:72
#3 0x0807c53a in stream_read (n_args=2, args=0xbfffdf04) at ../py/stream.c:97
#4 0x0806e5fa in fun_builtin_call (self_in=0x809a314 <mp_stream_read_obj>, n_args=2, n_kw=0,
args=0xbfffdf04) at ../py/objfun.c:93
#5 0x0806641e in mp_call_function_n_kw (fun_in=0x809a314 <mp_stream_read_obj>, n_args=2, n_kw=0,
args=0xbfffdf04) at ../py/runtime.c:572
#6 0x0806649f in mp_call_method_n_kw (n_args=1, n_kw=0, args=args@entry=0xbfffdf00)
at ../py/runtime.c:589
#7 0x08081c40 in mp_execute_bytecode (code_state=0xbfffdee0, inject_exc=0x0) at ../py/vm.c:992
#8 0x0806e7e0 in fun_bc_call (self_in=0xb7cc4f40, n_args=0, n_kw=0, args=0x0)
at ../py/objfun.c:239
#9 0x0806641e in mp_call_function_n_kw (fun_in=0xb7cc4f40, n_args=0, n_kw=0, args=0x0)
at ../py/runtime.c:572
#10 0x0806637b in mp_call_function_0 (fun=0xb7cc4f40) at ../py/runtime.c:546
#11 0x08089dba in execute_from_lexer (lex=0xb7cc5530, input_kind=MP_PARSE_SINGLE_INPUT,
is_repl=true) at main.c:123
#12 0x08089ffd in do_repl () at main.c:234
#13 0x0808ab64 in main (argc=1, argv=0xbffff1a4) at main.c:565
(gdb)

@dhylands
Copy link
Contributor Author

That will be the backtrace of where the Control-C was pressed. Try using continue and seeing if it segfaults.

Under gdb, you can use the handle command before running to cause SIGINT to not be captured by gdb, which means you won't be able to break into the program, but it will still stop if it gets a segfault.

(gdb) handle SIGINT nostop pass
SIGINT is used by the debugger.
Are you sure you want to change it? (y or n) y
Signal        Stop  Print   Pass to program Description
SIGINT        No    Yes Yes     Interrupt

@pfalcon
Copy link
Contributor

pfalcon commented Dec 16, 2015

Indeed, @dhylands rights, and backtraces above do not show segfault, which happens when running without gdb. Here're previous bugreports of this issue: micropython/micropython-lib#24 , #1035 .

So, if someone can help with triaging that and provide exact instructions how to reproduce segfault while running under gdb, that would be very helpful and appreciated.

@dhylands
Copy link
Contributor Author

I was able to reproduce the segfault running a 32-bit version of the code, however the backtrace was less than useful. I built micropython using:

make -B MICROPY_FORCE_32BIT=1 MICROPY_PY_FFI=0 DEBUG=1

and when I ran it and hit Control-C I got:

(gdb) handle SIGINT nostop pass
SIGINT is used by the debugger.
Are you sure you want to change it? (y or n) y
Signal        Stop  Print   Pass to program Description
SIGINT        No    Yes Yes     Interrupt
(gdb) run
Starting program: /home/dhylands/Dropbox/micropython/micropython/unix/micropython 
MicroPython v1.5.1-116-g8fb255d on 2015-12-16; linux version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>> import sys
>>> sys.stdin.read(1)
^C
Program received signal SIGINT, Interrupt.

Program received signal SIGSEGV, Segmentation fault.
0x010536c0 in ?? ()
(gdb) bt
#0  0x010536c0 in ?? ()
#1  0x00000002 in ?? ()
#2  0x00000063 in ?? ()
#3  0x00000000 in ?? ()

which suggests to me that it may be screwing up in the signal handler (not our code, but the kernel code). I threw some prints into the signal handler and immediately before and after the read (which seems to support this hypothesis), and I get the print leaving the signal handler, but I don't get the print after the read.

@dhylands
Copy link
Contributor Author

My build system for this was Ubuntu 14.04 LTS with gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
If I install gcc-4.9:

sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install gcc-4.9 g++-4.9

and build using:

make -B MICROPY_FORCE_32BIT=1 MICROPY_PY_FFI=0 DEBUG=1 CC=gcc-4.9

then the segfault goes away.

If you want to make gcc 4.9 be the default, then you can do:

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.9
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8
sudo update-alternatives --config gcc

The last command allows you to switch between using 4.8 or 4.9 as the default.

@robert-hh
Copy link
Contributor

I mentioned above that after the SIGINT catched by GDB, the c command would continue Micropython normally. So at the moment I see two ways to avoid the issue:
a) use gcc 4.9. That feels still a little bit uncomfortable as long as its not clear what the difference is. To avoid that, MicroPython could use its own dummy interrupt handler.
b) install an own dummy signal handler in your Python code. For a normal code using stdin, that might anyhow be useful to avoid Ctrl-C stopping the program.
I wonder what the REPL prompt does in respect to that, since it somehow deals with Ctrl-C, behaving similar to an Enter key being pressed.

@robert-hh
Copy link
Contributor

I tried to compile with gcc-4.9. That did not change the picture. I still get the Segmentation fault. Systen & gcc-version:
$ uname -a
Linux robert-VM-Mint 3.16.0-38-generic #5214.04.1-Ubuntu SMP Fri May 8 09:44:48 UTC 2015 i686 i686 i686 GNU/Linux
$ gcc --version
gcc (Ubuntu 4.9.3-8ubuntu2
14.04) 4.9.3
Copyright (C) 2015 Free Software Foundation, Inc.

@dhylands
Copy link
Contributor Author

I discovered that when you pass in CC=gcc-4.8 (or CC=gcc-4.9) it ignores the MICROPY_FORCE_32BIT=1 and builds a 64-bit executable. So I wasn't testing with a 32-bit executable.

I found I also had to install

sudo apt-get install gcc-4.9-multilib g++-4.9-multilib

and either switch to 4.9 as the default or use CC='gcc-4.9 -m32' to get a 32-bit executable, and indeed it still segfaults. And the backtrace under 4.9 looks more or less the same. And it leaves the signal handler and never gets to the line after the read. Which still suggests a problem outside of our code.

@robert-hh
Copy link
Contributor

Hi Dave, do you understand the difference between Ctrl-C, entered at the REPL prompt, which behaves stable, and Ctrl-C in the sys.stdin.read() call, which causes the segfault? Robert

@dhylands
Copy link
Contributor Author

@robert-hh Yep - If you look at the traces I did above, you'll see that Control-C was being pressed during sys.stdin.read(1). My problem (with 4.9) was that I was building a 64-bit executable (which doesn't segfault). Now that I'm actually building a 32-bit executable, it still segfaults (you may have missed my last comment).

@robert-hh
Copy link
Contributor

@dhylands Yes, I understand the traces and I have seen your comment. I was just wondering why Ctrl-C is catched well in one situation (REPL Prompt, reading from ?) and causes a segfault in another, while reading from stdin.

@pfalcon
Copy link
Contributor

pfalcon commented Dec 17, 2015

I was able to reproduce the segfault running a 32-bit version of the code, however the backtrace

@dhylands : Thanks for testing.

@pfalcon
Copy link
Contributor

pfalcon commented Dec 17, 2015

So at the moment I see two ways to avoid the issue:

Guys, instead of "avoiding" (== finding workarounds), it's better to push and fix it. Because once the real fix is found, effort on workarounds turns out to be waste of time.

@pfalcon
Copy link
Contributor

pfalcon commented Dec 17, 2015

(My previous comment assumes that you read linked pervious bugreports for this issue - seeing whole picture, it's clear that the issue is non-deterministic, so "solving" it by switching compiler is impossible, assuming otherwise means assuming that gcc 4.8 has bug in generating signal-related code for one of the most used platform, and that bug is not fixed in 4.8, but fixed in 4.9; that's about impossible.)

@pfalcon
Copy link
Contributor

pfalcon commented Dec 17, 2015

Segfault is fixed in 3db2b23 .

I was especially interested in fixing that, because for fixing 2nd part of the issue - raising KeyboardInterrupt. So, per my sly plan, cool way to do that is to raise it directly from signal handler. POSIX doesn't give indulgence to do it (actually, it doesn't approve of doing much less innocent things in signal handler). But it works well on Linux, per casual testing. But if it suddenly starts to segfault on somebody, we want to be sure, it's new segfault, not that boring old one. And of course, such solution needs to be tested on other supported platforms - macosx, freedos. (And then probably still #ifdefed).

@Anton-2
Copy link
Contributor

Anton-2 commented Dec 17, 2015

Then, for the record, with 3db2b23, there is no segfault on OS X (32 or 64bit build).
But I was not able to reproduce it previously...
The behavior is identical to @dhylands's report : raising OSError: 4 on first Ctrl-C, exit(1) for the second one.

@pfalcon
Copy link
Contributor

pfalcon commented Dec 17, 2015

Refactored in 3c2b377

@pfalcon
Copy link
Contributor

pfalcon commented Dec 17, 2015

@Anton-2 : Thanks for testing. So, as of 3db2b23, there're no known segfaults in signal handling, so you see the expected situation. That commit sets baseline for testing future changes, which yet need to be done (and may be risky).

@pfalcon
Copy link
Contributor

pfalcon commented Dec 17, 2015

Added basic support for handling Ctrl+C under windows in 2195046 , needs testing.

@dhylands
Copy link
Contributor Author

And I'll confirm that the segfault is gone with
3db2b23 and present without it (tested
using gcc 4.8 under Ubuntu 14.04).

On Thu, Dec 17, 2015 at 3:17 PM, Paul Sokolovsky notifications@github.com
wrote:

Added basic support for handling Ctrl+C under windows in 2195046
2195046
, needs testing.


Reply to this email directly or view it on GitHub
#1722 (comment)
.

Dave Hylands
Shuswap, BC, Canada
http://www.davehylands.com

@pfalcon
Copy link
Contributor

pfalcon commented Dec 19, 2015

Next step of solving this issue is posted as #1733 . It needs extensive testing on other systems than Linux. 2195046#commitcomment-15080573 gives quick overview of recommended testing process.

@robert-hh
Copy link
Contributor

Hi all, I did not know where the to-be-tested version is located, so I just took the Zip-File from https://github.com/micropython/micropython. Test environment:
Windows 7 64 bit; MINGW32, MSYS and Python 3.5.1 fresh installed from the net, just PATH adapted.
Step1: Micropython compile
micropython compile stops because of a warning in ../unix/mphalport.h:37 that 'usleep is deprecated'. So I had to turn off Werror to carry on. I do not get that warning on my office Windows machine with an older installation of MinGW.
Step 2: Test Ctrl-C
2.1: Ctrl-C at the REPL prompt: It behaves like 'enter' w/o printing a newline first. I would have expected that is cancels whatever was entered before. Same as on Linux. Unusual but OK.
2.2: Ctrl-C during a system call. tested with the notorious sys.stin.read(). Returns an empty string and a Traceback print.

>>> import sys
>>> sys.stdin.read(1)
''
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyboardInterrupt:
>>>

2.3: Ctrl-C during a small python script, consisting of nested loops and (hopefully) not doing system calls in between.

import math

def run():
    for i in range(1000):
        for j in range(1000):
            for k in range (50):
                cad = math.log(i*j*k + 1)

Started from the REPL Prompt, interrupted with Ctrl-C. Prints a traceback as expected:

>>> import loop
>>> loop.run()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "loop.py", line 7, in run
KeyboardInterrupt:
>>>

That could be repeated several times with identical result. Two unexpected (at least when the happened first) observations:
a) In rare cases, when I tried to exit Micropython, I got the error: "Assertion failed: !"bad free", file ../py/gc.c, line 477
b) Once in the test of calling loop.run(), micropython terminated after Ctrl-C instead of showing the REPL prompt. That was caused by the fact, that Ctrl-C does not flush the input queue (see also test 2.1). There was a Ctrl-D entered before Ctrl-C, which got active after termination of the loop.
Observation a) could be repeated with some probability by running test 2.3 a few times, and then terminating micropython by pushing Ctrl-D, but at no reliable pattern. Observation b) is repeatable.

@robert-hh
Copy link
Contributor

Just as a side note: If I do that on Linux, by first interrupting sys.stdin.read(1) with Ctrl-C, and then entering a command at the REPL prompt, that's what I get.

MicroPython v1.5.1 on 2015-12-19; linux version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>> import sys
>>> sys.stdin.read(1)
^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: 4
>>> 
>>> dir()
['sys', '__name__']
KeyboardInterrupt: 
>>> 

That may be caused by the attempt to do something reasonable with Ctrl-C instead of just interrupting and go back to the baseline.
A test on Window 10 showed similar behavior to Windows 7, just the printout after interrupting sys.stdin.read() looks a little bit different, by not printing an empty string.

>>> import sys
>>> sys.stdin.read(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyboardInterrupt:
>>>

P.S.: I'm happy to repeat tests on Windows, but usually I use it only for Office tasks and stuff that runs on Windows only, and very often on Windows XP only. My preferred environment for Python is Linux.

@pfalcon
Copy link
Contributor

pfalcon commented Dec 20, 2015

so I just took the Zip-File from https://github.com/micropython/micropython.

Thanks for being eager to test it, but nope, the above is not the right code to test - it doesn't contain #1733. What needs to be done is #1733 is applied on top of micropython master and that test. And it needs to be tested on MacOSX and FreeDOS, if you don't have access to those systems, there's nothing new to test (well, you can test it on Linux - it should work just like CPython3 modulo minor cosmetic diffs). If you test #1733, please post further comments directly to it. Thanks!

@stinos
Copy link
Contributor

stinos commented Dec 20, 2015

Test environment: Windows 7 64 bit; MINGW32, MSYS and Python 3.5

Note that windows builds use windows_mphal.c so pfalcon's changes to unix_mphal.c like in #1733 do not affect this environment. Also support for mingw (the one from http://mingw.org/ which I assume is what you mean with mingw32?) for uPy was basically dropped in favour of mingw-w64, because the latter supports 64bit build and more importantly it is still actively developped (afaik mingw is pretty much dead since 2013). As such it's probably also recommended to use MSYS2 instead for identical reasons.

@pfalcon
Copy link
Contributor

pfalcon commented Dec 20, 2015

Note that windows builds use windows_mphal.c so pfalcon's changes to unix_mphal.c like in #1733 do not affect this environment.

Yes. Nor #1733 would do any good for Windows, per above. So, #1733 is ultimate solution for Linux. It's unknown how it affects MacOSX and FreeDOS, so that needs to be tested before #1733 is merged. After that, Windows and bare-metal ports are left. Issues with them will be resolved in less efficient manner (there's still option to have efficient solution for Cortex-M3+).

@pfalcon pfalcon changed the title unix port doesn't handle Control-C from sys.stdin.read(1) Control-C isn't handled in all cases Dec 22, 2015
@pfalcon
Copy link
Contributor

pfalcon commented Dec 22, 2015

Ok, so #1733 is merged. From high-level perspective, it represents "fast path" for handling KeyboardInterrupt for unix sub-ports which support longjmp'ing out of signal handler. As I mentioned before, there should be possibility to provide similar fast path for Cortex-M3/M4 - longjmp out of PENDSV interrupt handler. This should be cute hack for folks who love dealing with tricks of a particular architecture, so welcome.

Otherwise, having fast paths (or ideas for fast path) for common cases, we need to provide general fallback solution which will work for everything else (at the expense of some loss of efficiency) and will solve all ctrl+c issues once and for all. In this regard, @stinos' #1738 isn't such solution, because it resolve it for Windows, but not baremetal ports.

Instead, I think it makes sense to follow @dpgeorge's previous suggestion to check pending exception not just for VM jump instructions, bit also for "ret". And I think we should follow @dhylands idea too and provide such check as a standalone function, so long-running builtin functions could use it easily (VM still should use inlined version of course for efficiency).

That's my plan, if anyone has criticism, please share it, otherwise I'll get to coding it when time permits.

@dpgeorge
Copy link
Member

As I mentioned before, there should be possibility to provide similar fast path for Cortex-M3/M4 - longjmp out of PENDSV interrupt handler. This should be cute hack for folks who love dealing with tricks of a particular architecture, so welcome.

stmhal already does this: first ctrl-C will signal to VM, and if that doesn't get through then second ctrl-C will rejig the stack to jump to the inner-most nlr handler. Or did you mean something else?

That's my plan

Sounds good!

@robert-hh
Copy link
Contributor

As far as I can tell from WiPy and Pyboard, a running script is interrupted by Ctrl-C, as well as the REPL prompt. Only "System" calls like sys.stdin.read() do not receive the interrupt until the next char is entered. Hitting Ctr-C twice does not work in that case.

@dpgeorge
Copy link
Member

Only "System" calls like sys.stdin.read() do not receive the interrupt until the next char is entered. Hitting Ctr-C twice does not work in that case.

It should on the pyboard. I just tested it and it does:

MicroPython v1.5.1-168-g1c9210b on 2015-12-23; PYBLITEv1.0 with STM32F411RE
Type "help()" for more information.
>>> import sys
>>> sys.stdin.read(1)
[hit ctrl-c two times]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyboardInterrupt: 
>>> 

@robert-hh
Copy link
Contributor

Confirmed, my fault. The latest build does the magic. No change for WiPy.

@danicampora
Copy link
Member

stmhal already does this: first ctrl-C will signal to VM, and if that doesn't get through then second ctrl-C will rejig the stack to jump to the inner-most nlr handler

OK I need to implement that for the WiPy.

@dlech
Copy link
Sponsor Contributor

dlech commented Mar 27, 2020

PEP 475 is implemented in #5723, which essentially does the same thing suggested in the original comment here.

@dpgeorge
Copy link
Member

Also, 5a91cd9 fixed the case of checking for pending exceptions right at the end of code execution. So I think this issue can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants