Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 323044

Summary: GTK: readAndDispatch returns true even if no events are outstanding
Product: [Eclipse Project] Platform Reporter: bugzilla01
Component: SWTAssignee: Platform-SWT-Inbox <platform-swt-inbox>
Status: CLOSED NOT_ECLIPSE QA Contact:
Severity: major    
Priority: P3 CC: daniel_megert, deepakazad, eclipse.felipe, ericwill, gheorghe, remy.suen, Silenio_Quarti
Version: 3.5.2   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:

Description bugzilla01 CLA 2010-08-18 10:58:10 EDT
Build Identifier: 3.5.2

Using SWT to host a XulRunner (1.8, 1.9, 1.9.1, 1.9.2) we randomly (and frequently) get 99% CPU usage because readAndDispatch returns true (i.e. there are events outstanding to be processed) although there is nothing to dispatch.
Therefore Display.sleep() in the main dispatch loop is not called and essentially we have something like "while(true){}".
We added some trace statements to readAndDispatch and could determine that this is due to "g_main_context_iteration" returning true.
Everything else ("runSettings" and "runPopups") returns false and the "eventQueue" object is null (because of this "runDeferredEvents" does pretty much nothing).

We have this problem with Ubuntu 9.10 and Ubuntu 10.04.

Reproducible: Sometimes

Steps to Reproduce:
Unfortunately I don't know exactly how to reproduce this scenario.
Comment 1 Deepak Azad CLA 2011-02-10 04:15:31 EST
(In reply to comment #0)
> Build Identifier: 3.5.2
Comment 2 Deepak Azad CLA 2011-02-10 04:30:31 EST
(In reply to comment #0)
> We added some trace statements to readAndDispatch and could determine that this
> is due to "g_main_context_iteration" returning true.
> Everything else ("runSettings" and "runPopups") returns false and the
> "eventQueue" object is null (because of this "runDeferredEvents" does pretty
> much nothing).
This can be reproduced with the following snippet and I20110201-0800

I ran into this while fixing Bug 330353 and Bug 336514.

-------------------------------------------------------------------------------
/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation

*******************************************************************************/
package org.eclipse.testsnippets;

/*
 * UI Automation (for testing tools) snippet: post key events
 *
 * For a list of all SWT example snippets see
 * http://www.eclipse.org/swt/snippets/
 * 
 * @since 3.0
 */
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;

public class TestSnippet {

public static void main(String[] args) {
    final Display display = new Display();
    final Shell shell = new Shell(display);
    final Text text = new Text(shell, SWT.BORDER);
    text.setSize(text.computeSize(150, SWT.DEFAULT));
    shell.pack();
    shell.open();
    new Thread(){
        public void run(){
            Event keyEvent = new Event();
            Event charEvent = new Event();
            System.out.println("STARTING");
            for (int i = 0; i < 5000; i++) {
                System.out.println(i);
                keyEvent.type = SWT.KeyDown;
                keyEvent.keyCode = SWT.MOD3;
                display.post(keyEvent);    

                charEvent.type = SWT.KeyDown;
                charEvent.character = 'a';
                display.post(charEvent);

                charEvent.type = SWT.KeyUp;
                charEvent.character = 'a';
                display.post(charEvent);

                keyEvent.type = SWT.KeyUp;
                keyEvent.keyCode=SWT.MOD3;
                display.post(keyEvent);
            }
        }    
    }.start();
    while (!shell.isDisposed()) {
        boolean readAndDispatch = display.readAndDispatch();
        System.out.println("readAndDispatch: "+ readAndDispatch);
        if (!readAndDispatch) display.sleep();
    }



    display.dispose();
}
}
-------------------------------------------------------------------------------(
Comment 3 Felipe Heidrich CLA 2011-02-10 15:26:21 EST
Your snippet is flooding the queue using postEvent, it makes sense to me that readAndDispatch returns true.
If you wait long enough, after all 20000 events are processed, does readAndDispatch returns false ?
Comment 4 Deepak Azad CLA 2011-02-14 04:19:34 EST
(In reply to comment #3)
> Your snippet is flooding the queue using postEvent, it makes sense to me that
> readAndDispatch returns true.
> If you wait long enough, after all 20000 events are processed, does
> readAndDispatch returns false ?
Yes, it returns false, but the thread wakes up and then it also returns true multiple times even though no more events are posted.

(In reply to comment #2)
> (In reply to comment #0)
> > We added some trace statements to readAndDispatch and could determine that this
> > is due to "g_main_context_iteration" returning true.
> > Everything else ("runSettings" and "runPopups") returns false and the
> > "eventQueue" object is null (because of this "runDeferredEvents" does pretty
> > much nothing).
Plus, I was also concerned about this behavior, as it did not look right to me. Do you think that it is ok for eventQueue to be null when g_main_context_iteration returns true?

Note that this does not happen every time, but should be easy to reproduce.
Comment 5 Felipe Heidrich CLA 2011-02-14 09:45:01 EST
(In reply to comment #4)
> Yes, it returns false, but the thread wakes up and then it also returns true
> multiple times even though no more events are posted.

It is because there are still events in the queue waiting to be dispached.

> Plus, I was also concerned about this behavior, as it did not look right to me.

For me it makes sense...

> Do you think that it is ok for eventQueue to be null when
> g_main_context_iteration returns true?

Yes, these are two different queues.
This eventQueue you are looking at is the queue for *SWT* post events, which is empty. 
g_main_context_iteration operates in the *native* event queue (internal to GTK, full of events). 

Bogdan, I believe this bug should be fixed as not eclipse, do you agree with me ?

Deepak, you can get your code to work just by adding a sleep inside your for statement. I think a few milisecond should be enough to allow the system to dispatch the events (that should avoid the queue from getting too big and it should prevent the CPU from getting to 99%).
Comment 6 Eric Williams CLA 2016-10-18 16:42:06 EDT
(In reply to Felipe Heidrich from comment #5)
> (In reply to comment #4)
> > Yes, it returns false, but the thread wakes up and then it also returns true
> > multiple times even though no more events are posted.
> 
> It is because there are still events in the queue waiting to be dispached.
> 
> > Plus, I was also concerned about this behavior, as it did not look right to me.
> 
> For me it makes sense...
> 
> > Do you think that it is ok for eventQueue to be null when
> > g_main_context_iteration returns true?
> 
> Yes, these are two different queues.
> This eventQueue you are looking at is the queue for *SWT* post events, which
> is empty. 
> g_main_context_iteration operates in the *native* event queue (internal to
> GTK, full of events). 
> 
> Bogdan, I believe this bug should be fixed as not eclipse, do you agree with
> me ?
> 
> Deepak, you can get your code to work just by adding a sleep inside your for
> statement. I think a few milisecond should be enough to allow the system to
> dispatch the events (that should avoid the queue from getting too big and it
> should prevent the CPU from getting to 99%).

I agree, this doesn't seem to be a bug in Eclipse IMO.