After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 701878 - Check wakeup() before iteration(TRUE) doesn't block
Check wakeup() before iteration(TRUE) doesn't block
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: mainloop
unspecified
Other All
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2013-06-08 20:10 UTC by Benjamin Otte (Company)
Modified: 2013-06-10 23:47 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
tests: Add a test for a specific invariant (1.90 KB, patch)
2013-06-08 20:10 UTC, Benjamin Otte (Company)
committed Details | Review
0001-gmain-Document-more-use-cases-of-g_main_context_wake.patch (1.65 KB, patch)
2013-06-10 17:37 UTC, Colin Walters
none Details | Review
updated for comments (1.63 KB, patch)
2013-06-10 18:19 UTC, Colin Walters
committed Details | Review

Description Benjamin Otte (Company) 2013-06-08 20:10:22 UTC
Some tools rely on this behavior, this test makes it "official". Okay to commit?
Comment 1 Benjamin Otte (Company) 2013-06-08 20:10:24 UTC
Created attachment 246331 [details] [review]
tests: Add a test for a specific invariant

See the documentation in the test. The invariant is used by
gnome-test-runner.
Comment 2 Allison Karlitskaya (desrt) 2013-06-08 20:11:43 UTC
I'm totally OK with this guarantee.  If someone has explicitly called wakeup() then this is a pretty strong hint that we ought to do so.

How about docs in _wakeup()?

They currently say

"""

If context is currently waiting in a poll(), interrupt the poll(), and continue the iteration process.

"""


which is just not true....
Comment 3 Benjamin Otte (Company) 2013-06-08 20:36:27 UTC
I'm currently struggling about what guarantee to give in the docs. Because what we really want to say is "will make sure (the internal function) g_main_context_poll() will stop blocking and not block again until g_main_context_check() is called the next time". Which is roughly as descriptive as "some magic happens here".

The problem is that g_main_context_check() is changing if g_main_context_iteration() will block currently. (Is that even how it's supposed to be?)

So what guarantee do you want to give in the docs? In particular because the concept of poll()ing is kinda not what we do anyway, so talking about it seems completely wrong.
Comment 4 Allison Karlitskaya (desrt) 2013-06-10 15:22:13 UTC
I think the guarantee needs to be in terms of which specific behaviour we define as being... defined.

In particular, I think that you should mention two things:

(a) calling g_main_context_wakeup() will cause the next g_main_context_ieration() to return without blocking.

(b) this pattern:

thread() {
  done = TRUE;
  g_main_context_wakeup();
}

while (!done)
  g_main_context_iteration(, TRUE);


is guaranteed race-free.
Comment 5 Colin Walters 2013-06-10 15:56:33 UTC
(In reply to comment #4)
> I think the guarantee needs to be in terms of which specific behaviour we
> define as being... defined.
> 
> In particular, I think that you should mention two things:
> 
> (a) calling g_main_context_wakeup() will cause the next
> g_main_context_ieration() to return without blocking.

That seems pretty clear.

> is guaranteed race-free.

As long as the assignment to "done" is made visible in other threads via GMutex or g_atomic_()
Comment 6 Colin Walters 2013-06-10 17:37:02 UTC
Created attachment 246422 [details] [review]
0001-gmain-Document-more-use-cases-of-g_main_context_wake.patch
Comment 7 Allison Karlitskaya (desrt) 2013-06-10 17:42:10 UTC
Review of attachment 246422 [details] [review]:

::: glib/gmain.c
@@ +4333,3 @@
+ *
+ *   g_atomic_int_inc (&tasks_run);
+ *   if (g_atomic_int_get (&tasks_run) == NUM_TASKS)

There is a semi-race here: two threads might end up calling wakeup() :)
Comment 8 Benjamin Otte (Company) 2013-06-10 17:51:30 UTC
You want to implement it with g_atomic_int_dec_and_test() and a remaining_tasks int I suppose. For clarity!
Comment 9 Colin Walters 2013-06-10 18:19:12 UTC
Created attachment 246431 [details] [review]
updated for comments
Comment 10 Dan Winship 2013-06-10 18:19:47 UTC
Comment on attachment 246422 [details] [review]
0001-gmain-Document-more-use-cases-of-g_main_context_wake.patch

>+ * If @context is currently waiting in g_main_context_iteration(),
>+ * cause it to return.  Otherwise, cause the next invocation of
>+ * g_main_context_iteration() to return.

Well, g_main_context_iteration() already returns. You need to say "return immediately" or something. Except that that suggests that it won't even dispatch other sources that are ready, which isn't true. I'd just leave it in terms of poll():

  If @context is waiting in a poll(), interrupt the poll() and
  continue the iteration process. If @context is not currently
  waiting in a poll(), this will cause its next poll() to
  return immediately.

>+ * This API useful

missing "is"

Another important use is: if you implement your own GSource type which is not based on fds or timeouts, you probably need to call this to wake up the context when your source becomes ready.
Comment 11 Benjamin Otte (Company) 2013-06-10 18:24:45 UTC
I talked about this with Ryan yesterday. I don't like using poll() in the docs because (a) we might not even poll at all and (b) you'd need to know what a poll() is to understand it. The thing I would say is probably "will not wait":

  If @context is currently waiting in g_main_context_iteration(),
  cause it to return.  Otherwise, cause the next invocation of
  g_main_context_iteration() to not wait.

I might use "block" instead of "wait" because the argument to g_main_context_iteration() is called may_block:

  If @context is currently blocking in g_main_context_iteration(),
  cause it to return.  Otherwise, cause the next invocation of
  g_main_context_iteration() to not block.
Comment 12 Dan Winship 2013-06-10 18:36:43 UTC
Sure. Possibly even "If @context is currently blocking in g_main_context_iteration() waiting for a source to become ready, cause it to stop blocking and return."
Comment 13 Benjamin Otte (Company) 2013-06-10 23:47:12 UTC
Pushed the two coimmits with the agreed-on changes.