Recursive locks in Vala and D-Bus service support for Vala interfaces

I have been whining about features that I want in Vala to Jürg. To make up for all the time he lost listening to me I decided to fix two Vala bugs.

The first bug I fixed was using a recursive mutex for lock statements. Code like this will work as expected now:

public class LockMe : GLib.Object { }
public class Executer : GLib.Object {
	LockMe o { get; set; }
	construct { o = new LockMe (); }
	void Internal () {
		lock (o) { }
	}
	public void Method () {
		lock (o) { Internal (); }
	}
}
public class App : GLib.Object {
	static void main (string[] args) {
		Executer e = new Executer ();
		e.Method ();
	}
}

Here’s a gdb session that most GLib programmers will recognize:

Breakpoint 1, 0x08048a87 in executer_Method ()
(gdb) break g_static_rec_mutex_lock
Breakpoint 2 at 0xb7e4d0e6
(gdb) cont
Continuing.
Breakpoint 2, 0xb7e4d0e6 in g_static_rec_mutex_lock ()
   from /usr/lib/libglib-2.0.so.0
(gdb) bt
#0  0xb7e4d0e6 in g_static_rec_mutex_lock () from /usr/lib/libglib-2.0.so.0
#1  0x08048b04 in executer_Method ()
#2  0x08049046 in app_main ()
#3  0x0804908a in main ()
(gdb) cont
Continuing.
Breakpoint 2, 0xb7e4d0e6 in g_static_rec_mutex_lock ()
   from /usr/lib/libglib-2.0.so.0
(gdb) bt
#0  0xb7e4d0e6 in g_static_rec_mutex_lock () from /usr/lib/libglib-2.0.so.0
#1  0x08048a6e in executer_Internal ()
#2  0x08048b0f in executer_Method ()
#3  0x08049046 in app_main ()
#4  0x0804908a in main ()
(gdb) cont
Continuing.
Program exited normally.
(gdb)

The second bug is supporting interfaces for D-Bus services in Vala. It goes like this:

using GLib;
[DBus (name = "org.gnome.TestServer")]
public interface TestServerAPI {
	public abstract int64 ping (string msg);
}
public class TestServer : Object, TestServerAPI {
	int64 counter;
	public int64 ping (string msg) {
		message (msg);
		return counter++;
	}
}
void main () {
	MainLoop loop = new MainLoop (null, false);
	try {
		var conn = DBus.Bus.get (DBus.BusType.SESSION);
		dynamic DBus.Object bus = conn.get_object (
			"org.freedesktop.DBus", "/org/freedesktop/DBus",
			"org.freedesktop.DBus");
		uint request_name_result = bus.RequestName ("org.gnome.TestService", 0);
		if (request_name_result == DBus.RequestNameReply.PRIMARY_OWNER) {
			// start server
			var server = new TestServer ();
			conn.register_object ("/org/gnome/test", server);
			loop.run ();
		} else {  // client
			dynamic DBus.Object test_server_object =
				conn.get_object ("org.gnome.TestService",
					"/org/gnome/test", "org.gnome.TestServer");
			int64 pong = test_server_object.ping ("Hello from Vala");
			message (pong.to_string ());
		}
        } catch (Error foo) { }
}