]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Make every co-routine state its own CodeBlock and bump state early
authorRico Tzschichholz <ricotz@ubuntu.com>
Sun, 17 Mar 2019 11:38:35 +0000 (12:38 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 10 Jan 2022 16:16:13 +0000 (17:16 +0100)
Fixes https://gitlab.gnome.org/GNOME/vala/issues/601

ccode/valaccodefunction.vala
codegen/valaccodebasemodule.vala
codegen/valaccodemethodcallmodule.vala
codegen/valaccodemethodmodule.vala
codegen/valagasyncmodule.vala
codegen/valagdbusclientmodule.vala
tests/Makefile.am
tests/asynchronous/bug789249.vala [new file with mode: 0644]

index 395ffdc8b131539b19fda21a11f22607877fb090..d346f5665c45964813535b7d864b77f3e6ee046e 100644 (file)
@@ -327,10 +327,31 @@ public class Vala.CCodeFunction : CCodeNode {
                add_statement (stmt);
        }
 
-       public void close () {
+       public void prepend_statement (CCodeNode stmt) {
+               stmt.line = current_line;
+               current_block.prepend_statement (stmt);
+       }
+
+       public void prepend_expression (CCodeExpression expression) {
+               prepend_statement (new CCodeExpressionStatement (expression));
+       }
+
+       public void prepend_assignment (CCodeExpression left, CCodeExpression right) {
+               prepend_expression (new CCodeAssignment (left, right));
+       }
+
+       public void close (CCodeBlock? block = null) {
+               //FIXME Don't ignore this invalid close without further action
+               if (block != null && statement_stack.index_of (block) >= 0) {
+                       return;
+               }
+
                do {
                        var top = statement_stack.remove_at (statement_stack.size - 1);
                        current_block = top as CCodeBlock;
+                       if (current_block == block) {
+                               current_block = null;
+                       }
                } while (current_block == null);
        }
 }
index db9a498cc889edeb3d778effdde5660819d58ce0..e4ad92883311b1281d86aafea7aa488a2c131438 100644 (file)
@@ -46,6 +46,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                public Map<string,int> closure_variable_count_map = new HashMap<string,int> (str_hash, str_equal);
                public Map<LocalVariable,int> closure_variable_clash_map = new HashMap<LocalVariable,int> ();
                public bool is_in_method_precondition;
+               public CCodeBlock? current_co_state_block;
 
                public EmitContext (Symbol? symbol = null) {
                        current_symbol = symbol;
@@ -5241,10 +5242,17 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                // set state before calling async function to support immediate callbacks
                                int state = emit_context.next_coroutine_state++;
 
-                               ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
+                               ccode.prepend_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
                                ccode.add_expression (async_call);
                                ccode.add_return (new CCodeConstant ("FALSE"));
+
+                               if (state > 0) {
+                                       ccode.close (emit_context.current_co_state_block);
+                                       emit_context.current_co_state_block = null;
+                               }
                                ccode.add_label ("_state_%d".printf (state));
+                               ccode.open_block ();
+                               emit_context.current_co_state_block = ccode.current_block;
                        }
 
                        creation_expr = creation_call;
index d7ac3f4b0b6348a10bc3692098d426fb7b2265ce..284c54de71a929a9315810e798da1a9e9c4f3ac7 100644 (file)
@@ -802,10 +802,17 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                        // set state before calling async function to support immediate callbacks
                        int state = emit_context.next_coroutine_state++;
 
-                       ccode.add_assignment (get_variable_cexpression ("_state_"), new CCodeConstant (state.to_string ()));
+                       ccode.prepend_assignment (get_variable_cexpression ("_state_"), new CCodeConstant (state.to_string ()));
                        ccode.add_expression (async_call);
                        ccode.add_return (new CCodeConstant ("FALSE"));
+
+                       if (state > 0) {
+                               ccode.close (emit_context.current_co_state_block);
+                               emit_context.current_co_state_block = null;
+                       }
                        ccode.add_label ("_state_%d".printf (state));
+                       ccode.open_block ();
+                       emit_context.current_co_state_block = ccode.current_block;
                }
 
                if (expr.is_assert) {
index ff6d679ac5195895871fda51201dae5ccaf81039..cf5b0e99662b240e259dbfad50a42eeb9aa4f71c 100644 (file)
@@ -492,6 +492,8 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
                                        // coroutine body
                                        ccode.add_label ("_state_0");
+                                       ccode.open_block ();
+                                       emit_context.current_co_state_block = ccode.current_block;
                                }
 
                                if (m.closure) {
index 4f130946e93c3e935cb7f65b543494dc6bc338b3..4515d1dd0919d1191cd382822e3741d3fcb1e083 100644 (file)
@@ -735,11 +735,19 @@ public class Vala.GAsyncModule : GtkModule {
                        return;
                }
 
+               // set state early to support immediate callbacks
                int state = emit_context.next_coroutine_state++;
 
-               ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
+               ccode.prepend_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
                ccode.add_return (new CCodeConstant ("FALSE"));
+
+               if (state > 0) {
+                       ccode.close (emit_context.current_co_state_block);
+                       emit_context.current_co_state_block = null;
+               }
                ccode.add_label ("_state_%d".printf (state));
+               ccode.open_block ();
+               emit_context.current_co_state_block = ccode.current_block;
                ccode.add_statement (new CCodeEmptyStatement ());
        }
 
index 697b0875875f298bbc251b9af5c643a43c4a7d3e..367f0b660000471a27a232df675a1b78ef969e41 100644 (file)
@@ -412,7 +412,13 @@ public class Vala.GDBusClientModule : GDBusModule {
                                ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
                                ccode.add_expression (ccall);
                                ccode.add_return (new CCodeConstant ("FALSE"));
+                               if (state > 0) {
+                                       ccode.close (emit_context.current_co_state_block);
+                                       emit_context.current_co_state_block = null;
+                               }
                                ccode.add_label ("_state_%d".printf (state));
+                               ccode.open_block ();
+                               emit_context.current_co_state_block = ccode.current_block;
 
                                ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_finish"));
                                ccall.add_argument (new CCodeCastExpression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_source_object_"), "GAsyncInitable *"));
index 1a5605deace13699d001b9b683c7c413c39fa854..60a41b4a538e55ca190f3a14caa4343939cb3a71 100644 (file)
@@ -719,6 +719,7 @@ TESTS = \
        asynchronous/bug762819.vala \
        asynchronous/bug777242.vala \
        asynchronous/bug783543.vala \
+       asynchronous/bug789249.vala \
        asynchronous/bug792660.vala \
        asynchronous/bug792942.vala \
        asynchronous/bug793158.vala \
diff --git a/tests/asynchronous/bug789249.vala b/tests/asynchronous/bug789249.vala
new file mode 100644 (file)
index 0000000..7e854d6
--- /dev/null
@@ -0,0 +1,16 @@
+static int counter = 0;
+
+static async void foo () {
+       counter++;
+       assert (counter <= 1);
+
+       // This is the simplest way to trigger the issue,
+       // it may happen due to GTask/ThreadPool/threads
+       // getting to call the callback before yield, too.
+       foo.callback ();
+       yield;
+}
+
+void main () {
+       foo.begin ();
+}