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) { }
}

5 thoughts on “Recursive locks in Vala and D-Bus service support for Vala interfaces”

  1. Recursive locks are generally a bad idea. They are often introduced to “fix” a deadlock caused by some form of reentrancy (via a callback or whatever), however most of the time they just turn the blindingly obvious deadlock backtrace into a very hard to find subtle reentrancy issue.

    I would be very vary to default to recursive locks.

  2. As alexl says. There’s a reason the kernel does it: recursive locks are generally a sign that your locking model is neither good enough nor sufficiently clearly documented.

    Oh well.

  3. We’ve decided to go for recursive locking because C# allows recursive usage of its lock statement too. Vala tries to mimic C# a little bit here and there, so I guess that’s why.

    I do agree, though. While developing in Vala, I however don’t want to care too much about locks being or not being recursive.

  4. I agree that it’s usually better to not depend on recursive locks when designing the locking model. However, this change is only about the integrated lock statement, which is just syntactic sugar.

    Vala previously used GMutex, which can be recursive or non-recursive depending on the platform, and now the behavior is the same as in C#, which makes sense as we use the same syntax.

    It’s still possible to explicitly use GMutex when you don’t use the lock statement.

Comments are closed.