On 08/12/2007, <b class="gmail_sendername">Guido van Rossum</b> &lt;<a href="mailto:guido@python.org">guido@python.org</a>&gt; wrote:<div><span class="gmail_quote"></span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
On Dec 8, 2007 9:57 AM, Gustavo Carneiro &lt;<a href="mailto:gjcarneiro@gmail.com">gjcarneiro@gmail.com</a>&gt; wrote:<br>&gt; On 08/12/2007, Guido van Rossum &lt;<a href="mailto:guido@python.org">guido@python.org</a>&gt; wrote:
<br>&gt;<br>&gt; &gt; On Dec 8, 2007 3:58 AM, Gustavo Carneiro &lt;<a href="mailto:gjcarneiro@gmail.com">gjcarneiro@gmail.com</a>&gt; wrote:<br>&gt; &gt; &gt; Not only that, but pygtk is a generic module;<br>&gt; &gt;<br>
&gt; &gt; What does &quot;generic&quot; mean in this context? Surely not that it applies<br>&gt; &gt; to other libraries than GTK?<br>&gt;<br>&gt; Well, actually this is also a PyGObject issue, not only PyGtk.&nbsp;&nbsp;PyGObject<br>
&gt; wraps GLib.&nbsp;&nbsp;GLib was created to serve the needs of Gtk+, but is useful by<br>&gt; itself for writing portable programs.&nbsp;&nbsp;Among other things, GLib offers a<br>&gt; generic &quot;main loop&quot;, which programs can use to do generic event-driven
<br>&gt; programming, such as timeouts, polling file descriptors, and doing other<br>&gt; work when the main loop becomes idle.<br>&gt;<br>&gt; You could argue that non-gtk programs are rare and we shouldn&#39;t worry too
<br>&gt; much about them.&nbsp;&nbsp;Maybe it&#39;s true, I don&#39;t know.<br>&gt;<br>&gt;<br>&gt; &gt; &gt; who are we to forbid the usage<br>&gt; &gt; &gt; of signals if python itself allows it?&nbsp;&nbsp;If we were to ignore signals<br>
&gt; then<br>&gt; &gt; &gt; sooner or later someone would come along and shout &quot;hey, signals work<br>&gt; just<br>&gt; &gt; &gt; fine in pure python, so why did pygtk have to break my signals?&quot;.<br>&gt; &gt;<br>
&gt; &gt; Um, signals don&#39;t &quot;work just fine&quot; in pure Python. And I would argue<br>&gt; &gt; they don&#39;t either in C. They are extremely subtle, and most code using<br>&gt; &gt; signals is broken in some way. Just try to read the sigaction() man
<br>&gt; &gt; page and claim you understand it.<br>&gt; &gt;<br>&gt; &gt; Unfortunately, in Unix there are some conditions that can only be<br>&gt; &gt; delivered using signals (e.g. SIGINTR, SIGTERM) and others for which
<br>&gt; &gt; your choices are either polling or signals (SIGCHILD, SIGWINCH).<br>&gt; &gt; Traditionally, solutions based on select() or poll() with a short<br>&gt; &gt; timeout (e.g. 20 or 100 ms) have worked well, as the number of
<br>&gt; &gt; instructions executed each time is really negligeable, and the<br>&gt; &gt; response time is still reasonable on a human time scale. Unfortunately<br>&gt; &gt; it seems recent developments in power management for ultra-low power
<br>&gt; &gt; devices have made this an issue again.<br>&gt; &gt;<br>&gt; &gt; Windows solves this more elegantly by having a unified &quot;wait for<br>&gt; &gt; multiple conditions&quot; system call which can wait on I/O, semaphores,
<br>&gt; &gt; and other events (within the same process or coming from other<br>&gt; &gt; processes). Unfortunately, in Unix, some events don&#39;t have a file<br>&gt; &gt; descriptor associated with them, and for those select()/poll() cannot
<br>&gt; &gt; be used.<br>&gt; &gt;<br>&gt; &gt; The best solution I can think of is to add a new API that takes a<br>&gt; &gt; signal and a file descriptor and registers a C-level handler for that<br>&gt; &gt; signal which writes a byte to the file descriptor. You can then create
<br>&gt; &gt; a pipe, connect the signal handler to the write end, and add the read<br>&gt; &gt; end to your list of file descriptors passed to select() or poll(). The<br>&gt; &gt; handler must be written in C in order to avoid the race condition
<br>&gt; &gt; referred to by Glyph (signals arriving after the signal check in the<br>&gt; &gt; VM main loop but before the select()/poll() system call is entered<br>&gt; &gt; will not be noticed until the select()/poll() call completes).
<br>&gt;<br>&gt; Funny that everyone mentions this solution, as it is the solution<br>&gt; implemented by my patch :-)<br><br>Mind pointing me to it again? I can&#39;t find it in the Python bug tracker.<br><br>&gt; Well, to be fair, it might not be _exactly_ what is implemented by the
<br>&gt; patch.&nbsp;&nbsp;Reading between the lines, I think what you mean is to have python&#39;s<br>&gt; C signal handler mostly untouched; it would only write a byte to a pipe _in<br>&gt; addition to_ the normal setting the flag and Py_AddPendingCall.
<br><br>Well, in many cases I see no problems with the current signal handler,<br>and people are used to it, so I&#39;m not sure what is gained by getting<br>rid of it.<br><br>&gt; The patch I submitted, on the other hand, completely removes the vector of
<br>&gt; flags and Py_AddPendingCall, and instead writes the number of the signal<br>&gt; that was raised into the pipe, and reads it back from the pipe in the Python<br>&gt; main loop.<br><br>I believe Py_AddPendingCall was meant to be used by other places
<br>besides the signal handling.</blockquote><div><br>True.&nbsp; The patch does not remove Py_AddPendingCall, only stops using it for signals.<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
&gt; Which is the best solution?&nbsp;&nbsp;I think my patch fixes two problems: 1. the<br>&gt; need to have a FD to wake up poll() (t o fix the problem with what we are<br>&gt; discussing in this thread), and 2. make Python&#39;s signal handling more
<br>&gt; reliable (not 100% reliable because it doesn&#39;t handle longer bursts of<br>&gt; signals than the pipe buffer can take, but at least is race free).<br><br>I think it&#39;s okay to drop signals if too many come. The FD should be
<br>put in non-blocking mode so the signal handler won&#39;t block forever.<br>Does Unix even promise that a signal gets delivered twice if it gets<br>sent quickly twice in a row?</blockquote><div><br>Good point.<br></div>
<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">&gt; My solution is being reject because people are afraid to touch the signal<br>&gt; handling code, which has its faults, but well know faults.&nbsp;&nbsp;But if I
<br>&gt; refactor the patch to keep the crappy-but-sort-of-working signal code, and<br>&gt; only enhance it with the pipe, maybe it will more likely get accepted.<br>&gt;<br>&gt; Do I understand correctly? :-)<br><br>Not really; I don&#39;t recall seeing your patch. And I object to your
<br>subjective description of the existing signal handling; it has served<br>us well enough.</blockquote><div><br>Sorry.&nbsp; I have to say existing code is very bad in order to convince people it is worth changing... :P<br><br>
Anyway, the approach of writing to a pipe and reading it back later appears (to me) simpler to read and understand.&nbsp; That should also count for something, right?<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I have a worry though -- if signal handlers *always* and *only*<br>communicate by writing a byte to a FD, does that mean that the VM main<br>loop will have to attempt to read a byte from a pipe every time it<br>checks for signals? That sounds very expensive for something that&#39;s
<br>not needed by the vast majority of Python applications.</blockquote><div><br>Yes, it would be expensive.&nbsp; Instead the patch uses a simple global boolean  value, set to true when a signal is received, after writing to the pipe.&nbsp; PyErr_CheckSignals() does not try to read from the pipe unless that value is true.
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> Plus, you will<br>have to expose the FD to the user so that it can be included in
<br>select() and poll() calls.</blockquote><div><br>Correct. <br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Anyway, let&#39;s see the patch first.
</blockquote><div><br><a href="http://bugs.python.org/issue1564547">http://bugs.python.org/issue1564547</a><br></div></div><br>-- <br>Gustavo J. A. M. Carneiro<br>INESC Porto, Telecommunications and Multimedia Unit<br>&quot;The universe is always one step beyond logic.&quot; -- Frank Herbert