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 763345 - 'g_simple_async_result_complete' is deprecated
'g_simple_async_result_complete' is deprecated
Status: RESOLVED FIXED
Product: vala
Classification: Core
Component: Code Generator: GAsync
unspecified
Other All
: Normal minor
: ---
Assigned To: Vala maintainers
Vala maintainers
: 764781 (view as bug list)
Depends on:
Blocks: 765738
 
 
Reported: 2016-03-08 20:46 UTC by Marcin Lewandowski
Modified: 2017-06-08 17:02 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
codegen: Use GTask instead of GSimpleAsyncResult if 2.36 target is selected (15.87 KB, patch)
2016-03-23 14:24 UTC, Carlos Garnacho
committed Details | Review
Require and target glib >= 2.36 (1.24 KB, patch)
2016-03-23 14:24 UTC, Carlos Garnacho
rejected Details | Review
Example of async methods used to create a generator (1.02 KB, text/plain)
2016-04-06 15:00 UTC, Al Thomas
  Details
NULL check for cancelled GTasks (1.16 KB, patch)
2016-04-27 22:36 UTC, Ben
committed Details | Review
codegen: Force sync behavior of GTasks (2.30 KB, patch)
2016-09-30 11:01 UTC, Carlos Garnacho
committed Details | Review

Description Marcin Lewandowski 2016-03-08 20:46:22 UTC
Vala 0.30.0 + GLib 2.46.2 issues the following warning if async methods are used:

warning: 'g_simple_async_result_complete' is deprecated [-Wdeprecated-declarations]
                g_simple_async_result_complete (_data_->_async_result);
Comment 1 Carlos Garnacho 2016-03-23 14:24:30 UTC
Created attachment 324592 [details] [review]
codegen: Use GTask instead of GSimpleAsyncResult if 2.36 target is selected

GTask brings some differences compared to GSimpleAsyncResult. Most namely,
g_task_return*() operations perform at once the async result data asignment
and the caller's main context activation. This is something that has to be
done exactly once, so the code flow has slight changes to ensure that.

Also, the async operation data used to be attached early through
g_simple_async_result_set_op_res_gpointer, only to be maybe replaced by
the real return data. If GTask is being used, we set this data through
g_task_set_task_data().
Comment 2 Carlos Garnacho 2016-03-23 14:24:35 UTC
Created attachment 324593 [details] [review]
Require and target glib >= 2.36

This enables the use of GTask by default, and gets rid of plenty of
deprecation warnings.
Comment 3 Carlos Garnacho 2016-03-23 14:34:47 UTC
I btw made sure that make check runs ok both with and without the last patch
Comment 4 Al Thomas 2016-03-31 10:35:48 UTC
Review of attachment 324593 [details] [review]:

Thanks for your work on bringing GTask to Vala.

The patch to increase the GLib version Vala depends on has been rejected 
because support is provided for building Vala on older distributions. The
example given on IRC #vala channel was a PPA for Ubuntu 12.04. The GLib
dependency was increased from 2.24 to 2.32 in February 2016. See
https://git.gnome.org/browse/vala/commit/?id=0b297f4273a868c90b8e96adf52380839fcc38c8
It is likely this won't be changed again for the next year or more.

This means anyone reviewing the main GTask patch should use the valac
--target-glib switch to use the new GTask code.
Comment 5 Carlos Garnacho 2016-03-31 11:39:09 UTC
(In reply to Al Thomas from comment #4)
> Review of attachment 324593 [details] [review] [review]:
> 
> Thanks for your work on bringing GTask to Vala.
> 
> The patch to increase the GLib version Vala depends on has been rejected 
> because support is provided for building Vala on older distributions. The
> example given on IRC #vala channel was a PPA for Ubuntu 12.04. The GLib
> dependency was increased from 2.24 to 2.32 in February 2016. See
> https://git.gnome.org/browse/vala/commit/
> ?id=0b297f4273a868c90b8e96adf52380839fcc38c8
> It is likely this won't be changed again for the next year or more.

Can't say much about this, besides: it's unfortunate that vala today chooses to use by default API that has been deprecated for ~3.5y unless some toggles are passed.

Maybe it should be possible to pass the default target glib in autogen/configure parameters, or autodetect that from installed glib at configure time? that'd make things friendly to people using vala with contemporaneous glib, while still allowing targeting older glibs for the PPA case.
Comment 6 Marcin Lewandowski 2016-03-31 12:21:51 UTC
I see no point in supporting ubuntu 12.04 as it is a) just maintained by ubuntu itself b) you can't even make apt-get update on it properly as repos are down.

If that's the only argument I think Vala should raise it's compatibility bar to ubuntu 14.04 which is the oldest normally supported LTS.
Comment 7 Al Thomas 2016-03-31 15:45:40 UTC
Carlos, Marcin, I agree with your sentiments. Please see https://bugzilla.gnome.org/show_bug.cgi?id=764420
Comment 8 Marcin Lewandowski 2016-04-01 18:49:40 UTC
I see their point that valac should make deterministic output regardless of GLib present in the system.

But as far as I understand discussion, they are not against doing this if --target-glib was explicitely specified. There are similar things in Vala already, e.g. you cannot call new Thread<void*>(something) unless you pass --target-glib 2.32 and this is accepted.

So maybe we should do the same with this patch? I mean that unless one explicitely sets --target-glib to the recent version, we keep the current behaviour?

I will reference this discussion in the another bug, maybe Jurg will share his thoughts.
Comment 9 Al Thomas 2016-04-01 19:25:10 UTC
(In reply to Marcin Lewandowski from comment #8)
> But as far as I understand discussion, they are not against doing this if
> --target-glib was explicitely specified. There are similar things in Vala
> already, e.g. you cannot call new Thread<void*>(something) unless you pass
> --target-glib 2.32 and this is accepted.

The latest stable major release of Vala, version 0.32.0, has GLib 2.32 as the default target. So once that release gets in to the distributions you will no longer need --target-glib 2.32 for the example you gave. It is good to know, though, that you didn't have a problem finding out about that feature toggle.
 
> So maybe we should do the same with this patch? I mean that unless one
> explicitely sets --target-glib to the recent version, we keep the current
> behaviour?

The patch already does this. That's what the context.require_glib_version (2, 36) checks are for.

I'm thinking now there should just be a warning that the old code path has been selected and that to use the new GTask code --target-glib 2.36 should be used. Something like:

warning: old async code generation has been selected, use --target-glib=2.36 to use the new GTask async code generation

This is similar to the test case given in https://bugzilla.gnome.org/show_bug.cgi?id=764420 for GtkTemplate. Vala gives an error:
error: glib 2.38 is required for using Gtk templates (with --target-glib=2.38)

Having a warning at least makes people aware the new code is available. If they are already using the --target-glib switch for 2.36+, because they use GtkTemplates for example, they will also get the GTask code without the option of downgrading. I don't know if that's a problem.

If a warning is agreed then an updated patch would be good. Then get a few people with good async knowledge to run the patch and say it works well, then push it out in a development release for wider testing. Hopefully the warning will get people interested.I don't know if you've seen, but someone on the mailing list has expressed an interest in doing work on async callbacks over the summer. So getting this patch tested and accepted before then would be good.
Comment 10 Marcin Lewandowski 2016-04-04 22:16:06 UTC
I think warning will do the job. Default can stay as it is + warning, but if new code is requested there's no reason to use deprecated one.
Comment 11 Al Thomas 2016-04-06 15:00:56 UTC
Created attachment 325486 [details]
Example of async methods used to create a generator

Example from https://wiki.gnome.org/Projects/Vala/AsyncSamples
Comment 12 Al Thomas 2016-04-06 15:03:58 UTC
Review of attachment 324592 [details] [review]:

The async generator example from https://wiki.gnome.org/Projects/Vala/AsyncSamples
compiles with this patch, but when run produces these runtime critical warnings:

Result: 0

(process:10286): GLib-GIO-CRITICAL **: g_task_return_pointer: assertion 'task->result_set == FALSE' failed
Result: 0

(process:10286): GLib-GIO-CRITICAL **: g_task_return_pointer: assertion 'task->result_set == FALSE' failed
Result: 0
Segmentation fault (core dumped)
Comment 13 Carlos Garnacho 2016-04-07 14:33:54 UTC
Hmmm, AFAICT that one highly relies in vala being able to issue g_simple_async_result_complete() in the lack of a main loop.

The difference here with GTask is that it does its own checks to maybe complete the task within g_task_return_pointer(), as can be seen in:

https://git.gnome.org/browse/glib/tree/gio/gtask.c#n1154

What happens in the specific situation of that test is that:

1) g_task_new() is created when there's no thread default main context, so the task stores the global default context in:
   https://git.gnome.org/browse/glib/tree/gio/gtask.c#n696

2) In g_task_return() (the link above), it checks whether the task context is the same than the current one. As there's no current main context, the task is not returned immediately.

3) A bit farther in that function, in:
   https://git.gnome.org/browse/glib/tree/gio/gtask.c#n1171
   it schedules the task to be finished in the next main context loop, which is never dispatched.

4) Because the task never ends, the int_generator_generate_ready() function in the generated C sources is never called, so it doesnt iterate properly and ends up poking the same data and the same task.

Now, AFAICT this would all work fine if the code was driven by a main loop. As it would do if GTask detected this situation and called g_task_return_now() immediately.

I think this comes down to talking with the glib developers, and see if this non-mainloop-driven GTask usage is something they'd want to support or not.
Comment 14 Ben 2016-04-22 18:37:21 UTC
I'm getting a crash in a _finish function where _data_ is null:

_data_ = g_task_propagate_pointer (G_TASK (_res_), NULL);
result = _data_->result;
Comment 15 Ben 2016-04-27 22:15:44 UTC
>If the task resulted in an error, or was cancelled, then this will instead return NULL and set error.

We need to check if _data_ is NULL in the case of cancelled tasks
Comment 16 Ben 2016-04-27 22:36:37 UTC
Created attachment 326901 [details] [review]
NULL check for cancelled GTasks
Comment 17 Dan Winship 2016-09-20 17:02:10 UTC
(In reply to Marcin Lewandowski from comment #0)
> Vala 0.30.0 + GLib 2.46.2 issues the following warning if async methods are
> used:
> 
> warning: 'g_simple_async_result_complete' is deprecated
> [-Wdeprecated-declarations]
>                 g_simple_async_result_complete (_data_->_async_result);

Note that if vala knows it is generating code for a specific target version of GLib, it could declare that in the generated code. Eg

  #undef GLIB_VERSION_MIN_REQUIRED
  #define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_44
  #include <gio/gio.h>
Comment 18 Dan Winship 2016-09-20 17:38:44 UTC
(In reply to Carlos Garnacho from comment #13)
> I think this comes down to talking with the glib developers, and see if this
> non-mainloop-driven GTask usage is something they'd want to support or not.

I don't think that makes sense. GTask behavior is explicitly defined in terms of GMainContext. (While the docs maybe aren't *100%* explicit about the fact that the callback is always called in a particular GMainContext, that's definitely the intention. I'm pretty sure that was entirely the intention with GSimpleAsyncResult too, it just didn't implement it automatically, so it was possible to subvert it...)

> Now, AFAICT this would all work fine if the code was driven by a main
> loop. As it would do if GTask detected this situation and called
> g_task_return_now() immediately.

GTask couldn't "detect" this, because it's indistinguishable from other cases where the current behavior is expected, like calling an _async() function from main() before starting the main loop. So if it was going to support this, it would have to be by adding "g_task_set_non_main_context_based()" or something to have the caller indicate that it wants the new behavior.
Comment 19 Carlos Garnacho 2016-09-30 11:01:03 UTC
(In reply to Dan Winship from comment #18)
> (In reply to Carlos Garnacho from comment #13)
> > I think this comes down to talking with the glib developers, and see if this
> > non-mainloop-driven GTask usage is something they'd want to support or not.
> 
> I don't think that makes sense. GTask behavior is explicitly defined in
> terms of GMainContext. (While the docs maybe aren't *100%* explicit about
> the fact that the callback is always called in a particular GMainContext,
> that's definitely the intention. I'm pretty sure that was entirely the
> intention with GSimpleAsyncResult too, it just didn't implement it
> automatically, so it was possible to subvert it...)

FWIW, I suspected the answer, and I do agree. Doing async calls without a running main loop to catch the results is a bit of handwaving at best, AFAICS the failing demo badly relies on turning async into sync through yield, which is fine I guess if all your async calls do that, but doesn't seem to scale to real-life situations.

Alas, this feature has been advertised, so we can't tell that there's no running code out there that does this. Nor we can add other than runtime warnings in the case this was deemed a not-so-necessary feature.

> 
> > Now, AFAICT this would all work fine if the code was driven by a main
> > loop. As it would do if GTask detected this situation and called
> > g_task_return_now() immediately.
> 
> GTask couldn't "detect" this, because it's indistinguishable from other
> cases where the current behavior is expected, like calling an _async()
> function from main() before starting the main loop. So if it was going to
> support this, it would have to be by adding
> "g_task_set_non_main_context_based()" or something to have the caller
> indicate that it wants the new behavior.

Same goes for vala generated code. I'm attaching a patch on top of the others that forces "return now" behavior on the same situations than the old code paths by iterating on the GTask main context until the task completes.

However, I've only done this to the code path affecting this demo. The other code path in valagasyncmodule.vala invariantly used g_simple_async_result_complete(), I'd rather not take this approach for the GTask paths if it's not essential.

With this patch the generator demo works just fine, as does Tracker (a heavy vala/async user) when built with these patches. If the approach looks ok-ish I'll squash the patches together and reattach.
Comment 20 Carlos Garnacho 2016-09-30 11:01:54 UTC
Created attachment 336630 [details] [review]
codegen: Force sync behavior of GTasks

There's code out there relying on immediate return here when state is
!=0. As GTask always defers the finalization to an idle in its main
context, ensure the source is dispatched and the task completed before
returning.
Comment 21 Carlos Garnacho 2016-09-30 11:31:18 UTC
Comment on attachment 326901 [details] [review]
NULL check for cancelled GTasks

Thanks for the patch BTW :), I however think it makes sense to just always do the NULL check, it will just never be true if there's no error from the GTask. Seems easier than iterating through the params to find a cancellable, which will most commonly be there.

I did this change locally.
Comment 22 Dan Winship 2016-09-30 13:38:05 UTC
Comment on attachment 336630 [details] [review]
codegen: Force sync behavior of GTasks

seems kind of scary... Another possibility would be to just import GSimpleAsyncResult into vala (and rename it and strip out the parts you aren't using, which is 90% of it).
Comment 23 Carlos Garnacho 2016-09-30 14:02:48 UTC
I admit it is... downside of that approach is that it's generated code which would need such object, so we're talking effectively about replicating an object, and possibly multiple namespaced instances of it in order to avoid function and g_type_register* clashes.
Comment 24 Dan Winship 2016-09-30 15:00:13 UTC
ah. well, in that case, it's not like there's any plan to ever actually remove anything from glib, so you could just continue to use GSimpleAsyncResult but emit "G_GNUC_BEGIN_IGNORE_DEPRECATIONS"/"G_GNUC_END_IGNORE_DEPRECATIONS" around the calls.
Comment 25 Al Thomas 2016-09-30 15:52:49 UTC
In some ways it would be nice to create a separate valagtaskasyncmodule.vala and enable that with an --enable-experimental-gtask-async-module switch to valac.

I'm not sure how practical that is. Ideally there would be an AsyncModule interface and the old and new objects would implement that to make them interchangeable.

The inheritance chain for GAsyncModule is:
Vala.GAsyncModule -> Vala.GtkModule -> Vala.GSignalModule -> Vala.GObjectModule -> Vala.GTypeModule -> Vala.GErrorModule -> Vala.CCodeDelegateModule -> Vala.CCodeArrayModule -> Vala.CCodeMethodCallModule -> Vala.CCodeAssignmentModule -> Vala.CCodeMemberAccessModule -> Vala.CCodeControlFlowModule -> Vala.CCodeMethodModule -> Vala.CCodeStructModule -> Vala.CCodeBaseModule -> Vala.CodeGenerator -> Vala.CodeVisitor

So GAsyncModule is a CodeVisitor that overrides visit_method (), visit_creation_method (), visit_yield_statement () and visit_return_statement (). It overrides a few methods from elsewhere, such as generate_method_declaration (). Vala uses the visitor pattern internally, but I haven't figured out where a single switch for --enable-experimental-gtask-async-module would work.

It's hard to tell how widespread the co-routines use case is. There is a note on Wikipedia stating "Vala implements native support for coroutines. They are designed to be used with a Gtk Main Loop, but can be used alone if care is taken to ensure that the end callback will never have to be called before doing, at least, one yield." See https://en.wikipedia.org/wiki/Coroutine#Implementations_for_Vala
Comment 26 Michael Gratton 2016-10-03 23:48:52 UTC
As an extra data point, Geary makes heavy use of async calls and it builds and seems to run fine when built with valac master with the patches above applied.
Comment 27 Rico Tzschichholz 2016-11-19 12:17:51 UTC
Attachment 324592 [details] pushed as 14ca2e0 - codegen: Use GTask instead of GSimpleAsyncResult if 2.36 target is selected
Comment 28 Rico Tzschichholz 2016-12-07 08:18:25 UTC
@carlosg: Hmm, any ideas on how to handle "g_task_get_completed" not being available in glib 2.36, other than bumping the requirement for this feature to glib 2.44.
Comment 29 Debarshi Ray 2017-01-22 12:15:26 UTC
*** Bug 764781 has been marked as a duplicate of this bug. ***