Be prepared to pull a Linda Blair here.

I've been diagnosing a problem, and finally think I've figured out
what's going on.

I'm on a Redhat 7.3 box, using PyGTK 0.6.9 and Python 1.5.2

Please do not say anything about upgrading anything, it ain't gonna
happen, so save your breath.

On to the problem.

I've got a FIFO I've created that I'm watching with the gtk input_add
function:

      self.fifo_tag = gtk.input_add(self.fifo, gtk.GDK.INPUT_READ, self.read_from_fifo)

The FIFO is made to be non-blocking, etc..
read_from_fifo basically reads and parsed stuff from the fifo, and
eventually places it in a Queue object:

self.io_queue.put( stuff )

So far so good.
I can do this all day.

Here is the hard part, and I've tried quite a few different mechanisms
to make this work properly.

The function 'handle_fifo' pops stuff off the Queue object and
eventually (usually, but not always) does stuff with it.  'stuff'
generally means doing some additional I/O and gtk things.

gtk things certainly involves messing with many widgets, clists, labels,
etc.. *and* measuring the progress of the I/O with a progress bar.

That's the rub.

To make progress bars work, I use the following code:

      while gtk.events_pending():
        gtk.mainiteration(0)

And here is where I get into trouble.

Assume the FIFO is still readable (perhaps I haven't read all of the
data, or perhaps new data has arrived).

It appears that gtk.mainiteration will call read_from_fifo *again*,
which calls handle_fifo, which may result in calling mainiteration,
which may result in read_from_fifo being called, which ....

Eventually something goes tilt and the app b0rks all over the place.
Very messy, needs a mop.

I've tried the following approaches:

1. don't call handle_fifo directly, use an idle function (same problem)
2. don't call handle_fifo directly, use a timeout function (same
problem)
3. [incorrectly] use gtk.threads_{enter,leave} <- many scary locks.
Wrong approach.
4. in handle_fifo, call gtk.input_remove(self.fifo_tag) and set
self.fifo_tag appropriately, and later re-enable it when my work is
done.  <- why doesn't this work?

The solution I came up with, and it's horrible, is to do this:

After the Queue has been populated, in read_from_fifo:

    old = gtk.events_pending
    def duh(*args):
      return 0
    gtk.events_pending = duh
    self.handle_fifo()
    gtk.events_pending = old

It works.

My questions:

1. is there a better way to do this?
2. why doesn't #4 above work?

What is the difference between calling mainiteration with blocking 0 or
1 (yeah, yeah, it "blocks".  What does that *mean*?)

I gotta say.  This was a monster stumper for me.  Took me like 4 hours
to figure it out.

--
"Never try to write to ROM - it wastes your time and annoys the ROM."

Jon Nelson <[EMAIL PROTECTED]>
C and Python Code Gardener
_______________________________________________
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to