Regression: Second try-catch block in async methods uses wrong C variable to access the error
- Reproducer:
// valac --save-temps --pkg=gio-2.0 makedirs.vala && ./makedirs
public async void make_dir(string path) {
var dir = File.new_for_path(path);
try {
yield dir.make_directory_async(GLib.Priority.DEFAULT, null);
} catch (GLib.Error e) {
stderr.printf("Error: %s\n", e.message);
}
try {
yield dir.make_directory_async(GLib.Priority.DEFAULT, null);
} catch (GLib.Error e) {
stderr.printf("Error: %s\n", e.message);
}
}
void main() {
var loop = new MainLoop();
GLib.FileUtils.set_contents("file.txt", "file.txt");
make_dir.begin("file.txt", (o, res) => {
make_dir.end(res);
loop.quit();
});
loop.run();
}
- Vala 0.43.4.11-b9837: makedirs.c
$ valac --save-temps --pkg=gio-2.0 makedirs.vala && ./makedirs
makedirs.vala:19.2-19.52: warning: unhandled error `GLib.FileError'
GLib.FileUtils.set_contents("file.txt", "file.txt");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Compilation succeeded - 1 warning(s)
Error: Error creating directory /home/fenryxo/dev/repo/vala-misc/file.txt: File exists
Error: Error creating directory /home/fenryxo/dev/repo/vala-misc/file.txt: File exists
- Vala 0.43.5.3-005acf: makedirs.c
$ valac --save-temps --pkg=gio-2.0 -X -g makedirs.vala && gdb --args ./makedirs
makedirs.vala:19.2-19.52: warning: unhandled error `GLib.FileError'
GLib.FileUtils.set_contents("file.txt", "file.txt");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Compilation succeeded - 1 warning(s)
GNU gdb (GDB) 8.2
(gdb) run
Starting program: /home/fenryxo/dev/repo/vala-misc/makedirs
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff7937700 (LWP 434)]
[New Thread 0x7ffff70d1700 (LWP 435)]
[New Thread 0x7ffff650a700 (LWP 436)]
Error: Error creating directory /home/fenryxo/dev/repo/vala-misc/file.txt: File exists
Thread 1 "makedirs" received signal SIGSEGV, Segmentation fault.
make_dir_co (_data_=0x555555567060) at /home/fenryxo/dev/repo/vala-misc/makedirs.c:193
193 _data_->_tmp6_ = _data_->_tmp5_->message;
(gdb) bt
#0 make_dir_co (_data_=0x555555567060) at /home/fenryxo/dev/repo/vala-misc/makedirs.c:193
#1 0x0000555555555567 in make_dir_ready (source_object=0x55555556f0c0, _res_=0x55555556b2e0, _user_data_=0x555555567060)
at /home/fenryxo/dev/repo/vala-misc/makedirs.c:128
#2 0x00007ffff7e9b8f9 in g_task_return_now (task=0x55555556b2e0) at ../gio/gtask.c:1148
#3 0x00007ffff7e9b93d in complete_in_idle_cb (task=0x55555556b2e0) at ../gio/gtask.c:1162
#4 0x00007ffff7cca528 in g_main_dispatch (context=0x555555565730) at ../glib/gmain.c:3182
#5 g_main_context_dispatch (context=context@entry=0x555555565730) at ../glib/gmain.c:3847
#6 0x00007ffff7cca918 in g_main_context_iterate (context=0x555555565730, block=block@entry=1, dispatch=dispatch@entry=1,
self=<optimized out>) at ../glib/gmain.c:3920
#7 0x00007ffff7ccac42 in g_main_loop_run (loop=0x555555566930) at ../glib/gmain.c:4116
#8 0x0000555555555c87 in _vala_main () at /home/fenryxo/dev/repo/vala-misc/makedirs.c:272
#9 0x0000555555555cc9 in main (argc=1, argv=0x7fffffffd388) at /home/fenryxo/dev/repo/vala-misc/makedirs.c:281
- The difference of the C code:
--- makedirs.old.c 2019-01-21 15:31:36.275630326 +0100
+++ makedirs.c 2019-01-21 15:31:46.884668256 +0100
@@ -1,4 +1,4 @@
-/* makedirs.c generated by valac 0.43.4.11-b9837, the Vala compiler
+/* makedirs.c generated by valac 0.43.5.3-005acf, the Vala compiler
* generated from makedirs.vala, do not modify */
/* valac --save-temps --pkg=gio-2.0 makedirs.vala && ./makedirs*/
@@ -189,10 +189,10 @@
_data_->_vala1_e = _data_->_inner_error_;
_data_->_inner_error_ = NULL;
_data_->_tmp4_ = stderr;
- _data_->_tmp5_ = _data_->_vala1_e;
+ _data_->_tmp5_ = _data_->e;
_data_->_tmp6_ = _data_->_tmp5_->message;
fprintf (_data_->_tmp4_, "Error: %s\n", _data_->_tmp6_);
- _g_error_free0 (_data_->_vala1_e);
+ _g_error_free0 (_data_->e);
}
__finally1:
if (G_UNLIKELY (_data_->_inner_error_ != NULL)) {
The problem is that the inner error is stored at _data_->_vala1_e
but null _data_->e
is used in the subsequent code.