[Python-bugs-list] [Bug #110694] PRIVATE: Threads and readline (PR#120)

noreply@sourceforge.net noreply@sourceforge.net
Wed, 13 Sep 2000 03:36:06 -0700


Bug #110694, was updated on 2000-Jul-31 14:28
Here is a current snapshot of the bug.

Project: Python
Category: None
Status: Closed
Resolution: Duplicate
Bug Group: Platform-specific
Priority: 5
Summary: PRIVATE: Threads and readline (PR#120)

Details: Jitterbug-Id: 120
Submitted-By: xfb52@dial.pipex.com
Date: Fri, 29 Oct 1999 14:33:55 -0400 (EDT)
Version: 1.5.2
OS: FreeBSD 3.2


When python is compiled with thread support and readline, ^C no longer
works properly (interpreter goes into an infinite loop).
(Tried with readline 2.0, 2.2 and 4.0).

The same system compiled without readline but with threads works fine,
and compiled without threads but with readline works fine.

The error seems to centre around the signal handler installed by
call_readline in Modules/readline.c which does not call signal_handler
in Modules/signalmodule.c (which is what happens without readline).

I have found an inadequate fix which works with readline-4.0 (but
not earlier realeases).  This makes ^C work but only after a RETURN
is pressed.  Whilst not perfect, it does at least allow readline
and threads.

Hopefully this may point someone who can better understand the signal
handling to find a better fix.

I confirm that, to the best of my knowledge and belief, this
contribution is free of any claims of third parties under
copyright, patent or other rights or interests ("claims").  To
the extent that I have any such claims, I hereby grant to CNRI a
nonexclusive, irrevocable, royalty-free, worldwide license to
reproduce, distribute, perform and/or display publicly, prepare
derivative versions, and otherwise use this contribution as part
of the Python software and its related documentation, or any
derivative versions thereof, at no cost to CNRI or its licensed
users, and to authorize others to do so.

I acknowledge that CNRI may, at its sole discretion, decide
whether or not to incorporate this contribution in the Python
software and its related documentation.  I further grant CNRI
permission to use my name and other identifying information
provided to CNRI by me for use in connection with the Python
software and its related documentation.

--Alex

*** Modules/readline.c  Fri Oct 29 19:31:13 1999
--- Modules/readline.c.ORIG     Fri Oct 29 19:14:27 1999
***************
*** 34,40 ****
  extern int rl_bind_key_in_map();
  extern int rl_initialize();
  extern int add_history();
- extern int rl_catch_signals;
  extern Function *rl_event_hook;
  #endif
  
--- 34,39 ----
***************
*** 233,239 ****
  static void
  setup_readline()
  {
-         rl_catch_signals=0;
        rl_readline_name = "python";
        /* Force rebind of TAB to insert-tab */
        rl_bind_key('\t', rl_insert);
--- 232,237 ----
***************
*** 277,283 ****
        int n;
        char *p;
        RETSIGTYPE (*old_inthandler)();
! /*    old_inthandler = signal(SIGINT, onintr); */
        if (setjmp(jbuf)) {
  #ifdef HAVE_SIGRELSE
                /* This seems necessary on SunOS 4.1 (Rasmus Hahn) */
--- 275,281 ----
        int n;
        char *p;
        RETSIGTYPE (*old_inthandler)();
!       old_inthandler = signal(SIGINT, onintr);
        if (setjmp(jbuf)) {
  #ifdef HAVE_SIGRELSE
                /* This seems necessary on SunOS 4.1 (Rasmus Hahn) */
***************
*** 288,294 ****
        }
        rl_event_hook = PyOS_InputHook;
        p = readline(prompt);
! /*    signal(SIGINT, old_inthandler); */
        if (p == NULL) {
                p = malloc(1);
                if (p != NULL)
--- 286,292 ----
        }
        rl_event_hook = PyOS_InputHook;
        p = readline(prompt);
!       signal(SIGINT, old_inthandler);
        if (p == NULL) {
                p = malloc(1);
                if (p != NULL)




====================================================================
Audit trail:
Tue Nov 02 20:44:47 1999	guido	changed notes
Tue Nov 02 20:44:47 1999	guido	moved from incoming to platformbug
Wed Nov 03 10:41:38 1999	guido	changed notes
Wed Nov 03 10:41:39 1999	guido	changed notes
Wed Nov 03 10:44:43 1999	guido	changed notes

Follow-Ups:

Date: 2000-Aug-01 14:02
By: none

Comment:
From: Guido van Rossum <guido@CNRI.Reston.VA.US>
Subject: Re: [Python-bugs-list] PRIVATE: Threads and readline (PR#120)
Date: Mon, 01 Nov 1999 17:53:46 -0500

> When python is compiled with thread support and readline, ^C no longer
> works properly (interpreter goes into an infinite loop).
> (Tried with readline 2.0, 2.2 and 4.0).

Thanks for your bug report.  I see that you are using FreeBSD.  Could
it be a FreeBSD related problem?  I don't see the same thing on
Solaris or Red Hat Linux.

Also, can you describe exactly how you reproduce the problem?

--Guido van Rossum (home page: http://www.python.org/~guido/)

-------------------------------------------------------

Date: 2000-Aug-01 14:02
By: none

Comment:
From: Guido van Rossum <guido@CNRI.Reston.VA.US>
Subject: Re: [Python-bugs-list] PRIVATE: Threads and readline (PR#120)
Date: Wed, 03 Nov 1999 10:40:18 -0500

Resolution.

------- Forwarded Message

Date:    Wed, 03 Nov 1999 15:24:59 +0000
From:    Alex Zbyslaw <xfb52@dial.pipex.com>
To:      guido@cnri.reston.va.us
Subject: Re: [Python-bugs-list] PRIVATE: Threads and readline

I believe that you were right and that this is a FreeBSD bug.  I finally
traced  the problem back to the use of the setjmp/longjmp in
readline.c.  For whatever reason, this messes up on FreeBSD.

I'll post my final patches on comp.lang.python myself.  Please consider
the problem closed.

Thanks for following up.  I think I'll stick to FreeBSD.  I grew up on
BSD4.2/3 and system v still gives me the heebie jeebies :-)

All the best,

- --Alex

------- End of Forwarded Message


-------------------------------------------------------

Date: 2000-Aug-01 14:03
By: none

Comment:
From: Guido van Rossum <guido@CNRI.Reston.VA.US>
Subject: Re: [Python-bugs-list] PRIVATE: Threads and readline (PR#120)
Date: Wed, 03 Nov 1999 10:42:33 -0500


------- Forwarded Message

Date:    Tue, 02 Nov 1999 11:57:23 +0000
From:    Alex Zbyslaw <xfb52@dial.pipex.com>
To:      guido@cnri.reston.va.us
Subject: RE: Re: [Python-bugs-list] PRIVATE: Threads and readline

>> When python is compiled with thread support and readline, ^C no longer
>> works properly (interpreter goes into an infinite loop).
>> (Tried with readline 2.0, 2.2 and 4.0).

>Thanks for your bug report.  I see that you are using FreeBSD.  Could
>it be a FreeBSD related problem?  I don't see the same thing on
>Solaris or Red Hat Linux.
>
>Also, can you describe exactly how you reproduce the problem?
>
>--Guido van Rossum (home page: http://www.python.org/~guido/)

Thanks for your mail, Guido.  Yes, I suppose it could be a FreeBSD
problem, though I was originally put on to the readline connection by
some articles in comp.lang.python which mentioned extremely similar
symptoms under Debian Linux.  What those articles did not mention was
the thread connection which I guessed for myself.  See articles titled
"Control-C on Unix meisbehaviour?" on 18th Oct 1999.  People in that
thread reported similar problems on various systems, whilst others had
no problem on apparently identical systems.  No one mentioned if they
had thread support.

Creating the problem is, for me, simple.  I compile python 1.5.2 with
thread support enabled.  (Thread and signal tests are passed by make
test and a quickie thread program works as expected).  If I go into the
interpreter
	python
and type ^C, everything goes into an infinite loop.

If I recompile python without threads, but with readline, then go into
the interpreter then press ^C I get KeyboardInterrupt as expected.

If I recompile with threads but without readline, then again, I get
KeyboardInterrupt as expected.

In all three cases, pressing ^C while a program is running gets correct
behaviour.



>From what I can determine:
	The readline module was written so that it bypassed any signal handler
installed by the readline library.  It institutes its own handler in
readline.c (onintr) which catches the interrupt and returns NULL (which
somewhere back down the line is interpreted as KeyboardInterrupt).

	However, with threads enabled (but no readline) there seems to be a
different behaviour, where the interrupt is caught by the regular signal
handler (I forget the name but its in my bug report - in
signalmodule.c).  My guess was that with threads enabled this signal
handler was doing something important.  But with readline support turned
on, this handler was not being called which caused some problem occur. 
I did try adapting the code in readline.c to call this signal handler
itself, but that didn't seem to work (though I forget what happened).

What my patch does is to forget about the local signal handler 'onintr'
and, instead, stick with whatever the "default" signal handler is. 
readline_4.0 allows you to turn off any signal handling in the readline
library itself, so the "default" handler will be whatever python
installs (in signalmodule.c).

This then "works" in that pressing ^C does not generate an infinite
loop.  But the call_readline function in readline.c does not immediately
return NULL, so you have to press RETURN before the KeyboardInterrupt is
generated.  

I never did figure out a way to both call the default signal handler and
return a NULL from call_readline -- which I believe would cause
"correct" ^C behaviour.  My C is somewhat rusty as I spend my time in
Python (by choice) and Perl (by neccessity).


I'm not sure what else I can tell you about the problem, but if there is
any more data I could provide for you, please ask.



As another bizarre data point: when I run a threaded python interpreter
on a program which does not use threads, and pipe the output to less,
less gets very confused and fails to update about half the screen,
leaving it blank.  This happens after hitting SPACE a couple of times. 
All the data is there, and if I jump less to the end of input and then
go back through the the data, I can see it all normally. Same program
and unthreaded python and less works just fine.  If you have ANY idea
why adding thread support could affect a program further down a pipe I'd
love to know.


By the way, I have no objection to making my bug report and patch
public, as long as there is some way to remove my email address from
it.  I have had only one piece of spam in the last year and I'd like to
keep it that way :-) As the good cafe owner said "Spam's orf"!  Although
it's not perfect, the patch has made threaded python usable for me. If
there are other people out there in the same boat and it helped them,
that would be great.


- -- 
Phone: 0131 468 2422
Email: xfb52@dial.pipex.com

------- End of Forwarded Message


-------------------------------------------------------

Date: 2000-Aug-01 14:03
By: none

Comment:
From: Jack Jansen <jack@oratrix.nl>
Subject: Re: [Python-bugs-list] PRIVATE: Threads and readline (PR#120)
Date: Wed, 03 Nov 1999 23:32:19 +0100

> As another bizarre data point: when I run a threaded python interpreter
> on a program which does not use threads, and pipe the output to less,
> less gets very confused and fails to update about half the screen,
> leaving it blank.  This happens after hitting SPACE a couple of times. 
> All the data is there, and if I jump less to the end of input and then
> go back through the the data, I can see it all normally. Same program
> and unthreaded python and less works just fine.  If you have ANY idea
> why adding thread support could affect a program further down a pipe I'd
> love to know.

As I like puzzles I spent some time thinking on this, and it must be
either (a) kernel bug, (b) a very strange stdio bug or (c) an incorrect 
observation. If your system supports memory-mapped I/O and stdio uses
it and it can somehow signal that a whole buffer is available while it 
isn't but only the tail end is available (because it uses an
overlapping memcopy which goes back-to-front, for instance) the reader 
in the pipe might wakeup too early and see null bytes. But if this was 
a bet I think I'd put my money on (c) (but absolutely no offense meant!).
--
Jack Jansen             | ++++ stop the execution of Mumia Abu-Jamal ++++
Jack.Jansen@oratrix.com | ++++ if you agree copy these lines to your sig ++++
www.oratrix.nl/~jack    | see http://www.xs4all.nl/~tank/spg-l/sigaction.htm 

-------------------------------------------------------

Date: 2000-Aug-01 14:03
By: none

Comment:
From: Guido van Rossum <guido@CNRI.Reston.VA.US>
Subject: Alex Zbyslaw: RE: Re: [Python-bugs-list] PRIVATE: Threads and readline (PR#120)
Date: Mon, 08 Nov 1999 10:30:24 -0500


------- Forwarded Message

Date:    Sat, 06 Nov 1999 11:17:00 +0000
From:    Alex Zbyslaw <xfb52@dial.pipex.com>
To:      guido@cnri.reston.va.us
Subject: RE: Re: [Python-bugs-list] PRIVATE: Threads and readline

This is the message I posted today on comp.lang.python.

Btw, I forgot to mention that to compile for thread support on FreeBSD
3.2 (and I would think 3.3) you only need to specify "-pthread" on the
link line.  That automatically links in the threaded C libraries. 
Everything else from the standard configure would appear to be correct.

All the best,

- --Alex


Subject:  Re: Control-C on Unix misbehaviour?
Date:  Sat, 06 Nov 1999 11:08:05 +0000

Quinn Dunkan wrote:
>
> On Mon, 18 Oct 1999 15:47:52 +0200, flight@mathi.uni-heidelberg.de
> Here's a data point for Irix6:
> If you hit ^C at the >>> prompt with readline loaded (python 1.5), python
> stops responding.  Further ^Cs do nothing, in fact the only way I've found
> to get out is to kill from another shell or hit ^z kill %.

I had exactly the same problem on FreeBSD 3.2  but ONLY when I had
thread support enabled.

I have eventually tracked the problem down to a bad interaction (read
library/kernel bug) between threads/sigjmp and interrupted reads.

I have created two "fixes" which can be applied either to a) python or
b) python and readline which fix the problems differently.  The fixes
are pretty trivial and so far they work for me.  You can check them out
at http://www.xfb52.dial.pipex.com/patches/python.shtml

I don't know how they may affect people who have had ^C dumping them
into a shell.  No one else has mentioned whether they had thread support
enabled or not.

>From extensive poking around I am quite sure that this misbehaviour is
not a bug in either Python or readline.

Good luck,

- --Alex

------- End of Forwarded Message


-------------------------------------------------------

Date: 2000-Aug-01 14:03
By: none

Comment:
There is a problem with threads + readline + signals on FreeBSD.
Apparently readline is using longjmp and this messes things up.
(I told you longjmp was evil. :-)
-------------------------------------------------------

Date: 2000-Sep-07 15:04
By: jhylton

Comment:
Please do triage on this bug.
-------------------------------------------------------

Date: 2000-Sep-13 03:36
By: gvanrossum

Comment:
According to the comments, at least part of this is a FreeBSD specific kernel problem and solved for that platform. Th rest (signals, threads, readline) is a duplicate of bug #110611. Closing this one.
-------------------------------------------------------

For detailed info, follow this link:
http://sourceforge.net/bugs/?func=detailbug&bug_id=110694&group_id=5470