On Wed, Mar 12, 2003 at 07:58:58AM -0600, Jon Nelson wrote:
> On Wed, 12 Mar 2003, John K Luebs wrote:
>
> > On Tue, Mar 11, 2003 at 09:15:06AM -0600, Jon Nelson wrote:
> > > Did anybody come up with anything better than this?
> > >
> > > In the callback which was used in input_add:
> > >
> > > old = gtk.events_pending
> > > def duh(*args):
> > > return 0
> > > gtk.events_pending = duh
> > > self.do_real_work_with_data_read_from_file(data_read_from_file)
> > > gtk.events_pending = old
> > >
> > > for this problem?
> > >
> > > The reason this appears necessary is explained below.
> > > *Somebody* has a better solution, I'm sure of it!
> >
> > This seems really silly.
> > If you're gonna f up events_pending in this way, then that means you are
> > not going to ever pump the gtk event queue. If you really don't need to
> > call mainiteration, then why don't you just remove the whole
> > while gtk.events_pending(): gtk.mainiteration nonsense.
>
> Actually, it means that gtk.events_pending() will always return 0 while
> the function self.do_real_work_with_data_read_from_file is being run.
My point being that if you're going to nullify the gtk.events_pending
test, then that will reduce to :
while 0: gtk.mainiteration()
which of course is a no-op.
>
> > Now the problem that you are running into is that select()/poll() and
> > the glib FD polling mechanism are all level sensitive. When you
> > input_add your fd, you are going to be notified whenever a read will not
> > block. This means that if the OS had buffered 200 bytes, you were
> > notified and only read 100 bytes, you will get the event again. Realize,
> > that this is basically a good design, don't fight it.
>
> I am quite aware of how select looping works. If you had read the whole
> thread (which it's clear you haven't) you would know that there is a
> fundamental problem with timeout, I/O, and idle event functions -- they
> can't do this:
Well, I did read the whole thread, but I forgot the details of what you
had tried. That doesn't necessarily mean I am wrong. I don't believe
there is the problem you allude to. This view comes from experience. In
the past, I have had very little trouble with these parts of GTK+. I
have had a lot more trouble with my own code. Based on the evidence you
have provided I still suspect the problem is in your code, not GTK+.
Of course, it is entirely possible there is a problem in your particular
versions of GTK+/pyGTK. Let's see.
>
> while events.pending():
> gtk.mainiteration()
>
> And the reason is that timeout, I/O, and idle events will get called,
> again, in the nested mainiteration (if appropriate). Additionally,
> using the gtk I/O monitoring functions to remove the callback *in* the
> callback doesn't appear to work, because it's entirely possible that
> data arrives for the file *after* the read operation.
Unfortunately, I can't reproduce your problem. Try this script, and see
what happens. If it works as I describe, then you have a bug in your
code. If it doesn't, then there is some change between 0.6.11 (highly
unlikely because this stuff is handled in GTK+) and 0.6.9 or between
GTK+ 1.2.10 and whatever you're using. This is again very unlikely. I
feel it's unlikely, because I looked around at the old GTK+ 1.2.7-1.2.10
revs in CVS and I could find no "interesting" changes to the mainloop
implementation.
Here is the script to try:
<<CUT HERE>>
import gtk
import os
def in_avail(cond, fd):
print "in_avail"
#gtk.input_remove(ia)
while gtk.events_pending(): gtk.mainiteration()
p = os.popen('yes', 'r')
ia = gtk.input_add(p.fileno(), gtk.GDK.INPUT_READ, in_avail)
gtk.mainloop()
<<CUT HERE>>
I open a pipe to yes which will give me the input condition. When I
have the input_remove line commented, in_avail will be reentered with
each mainiteration, and it is only a few milliseconds before I get
screenfulls of Maximum Recursion exceptions. Unbounded reentrancy, that
is.
Now, uncomment the input_remove line. What that will do is disconnect
the "connection" between the read condition (which will still exist if
it is poll/selected) and the callback in_avail. Doing that, you should
get "in_avail" printed, and the program should stop dead, because there
are no pending events and there never will be in this cruddy little
program.
I tested this with pygtk 0.6.11, GTK+ 1.2.10, and it works as I
described, which how it should according to the docs.
--jkl
_______________________________________________
pygtk mailing list [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/