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 672094 - Vala fails to initialize lock before first usage
Vala fails to initialize lock before first usage
Status: RESOLVED WONTFIX
Product: vala
Classification: Core
Component: general
0.15.x
Other Linux
: Normal normal
: ---
Assigned To: Vala maintainers
Vala maintainers
Depends on:
Blocks:
 
 
Reported: 2012-03-14 20:20 UTC by Adam Dingle
Modified: 2014-06-27 19:47 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Adam Dingle 2012-03-14 20:20:27 UTC
To see the problem, run the following program:

===
class Foo {
    static Foo instance = null;

    public static Foo get_instance() {
        lock (instance) {
            if (instance == null)
                instance = new Foo();
        }
        return instance;
    }
}

int thread_func() {
    stdout.puts("thread started\n");
    Foo.get_instance();
    stdout.puts("thread exiting\n");
    return 0;
}

void main() {
    try {
        for (int i = 0; i < 5 ; ++i)
            Thread.create<int>(thread_func, false);
    } catch (ThreadError e) {
        error(e.message);
    }
    Thread.usleep(10000000);
}
===

On my 4-core machine (running Vala 0.15.2 and Ubuntu 12.04), the program's output typically looks like this:

===
thread started
thread started
thread started
thread started
thread started
thread exiting
===

One or more threads successfully complete execution, but one or more threads remain deadlocked in the lock statement, unexpectedly.

I *believe* that what's happening is that Vala is calling g_static_rec_mutex_init to initialize the lock only after some threads are already waiting in the lock() statement.  Then those threads remain deadlocked, I think.

(By the way, this problem recently caused a subtle hang in Shotwell, which was using the design pattern above to initialize certain singleton objects.)
Comment 1 Evan Nemerson 2012-06-20 09:23:41 UTC
Static fields in Vala are initialized in the class initialization function (as they are supposed to be--see http://developer.gnome.org/gobject/stable/gobject-Type-Information.html#GClassInitFunc), and you are indeed trying to use the lock before that occurs (basically when the first instance of Foo is created).  In my opinion this test case failing isn't actually a bug, it is the expected behavior.  I the same pattern from time to time, and I didn't realize it was broken until now.

The problem is that I don't see a good way to do it right now... the only think I can think of would be using external code to initialize a mutex /before/ calling Foo.get_instance, which is moderately horrible.

Perhaps fixing #627293 would be the right solution?  Then you could just do something like


public static Foo get_instance () {
  once {
    instance = new Foo ();
  }
  return instance;
}
Comment 2 Adam Dingle 2012-06-21 17:22:03 UTC
Yes, that would be great.
Comment 3 Evan Nemerson 2014-06-27 19:47:52 UTC
GOnce has been in for a while (Thu Apr 18 12:11:08 2013 +0200), though not with syntax support as above.  However, it should be usable, and I don't think there is a solution to this without something like __attribute__((constructor)) (which isn't portable), so I'm going to close this.  If the GOnce stuff is insufficient please reopen.