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 754027 - Don't use C constructors for initializing critical sections on Windows
Don't use C constructors for initializing critical sections on Windows
Status: RESOLVED OBSOLETE
Product: GStreamer
Classification: Platform
Component: orc
git master
Other Linux
: Normal enhancement
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2015-08-24 14:39 UTC by Nirbheek Chauhan
Modified: 2018-11-03 10:48 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Don't use C constructors for initializing critical sections on Windows (3.73 KB, patch)
2015-08-24 14:39 UTC, Nirbheek Chauhan
none Details | Review

Description Nirbheek Chauhan 2015-08-24 14:39:29 UTC
Created attachment 309924 [details] [review]
Don't use C constructors for initializing critical sections on Windows

Instead, use memory barriers and just initialize it as part of orc_init().
Also, require that some sort of threading library be available.

C constructors are toolchain-specific which brings its own set of problems.
There's no guarantees about the order in which C constructors are called, it
makes it impossible to use static libraries built with one toolchain on another
one, and so on.

Finally, C constructors are only useful when you need a single point of entry
for initializing data shared throughout the library. Orc already has a function
for doing that; namely orc_init(), so we can just use that.

The atomic set/get of cs_inited using MemoryBarrier() was inspired by GLib's
g_atomic_int_set/get implementation.
Comment 1 Sebastian Dröge (slomo) 2015-08-24 15:06:59 UTC
I'm all for it, library constructors are a disease :)
Comment 2 Nirbheek Chauhan 2015-08-24 16:02:11 UTC
I'll be testing this properly on Windows in a little while; will update the bug when I do so. Please don't merge till then. ;)
Comment 3 Olivier Crête 2015-08-24 16:33:05 UTC
Shouldn't the whole of orc_init() happens in a constructor instead...
Comment 4 David Schleef 2015-08-25 21:47:47 UTC
Calling orc_init() is not required in order to use orc-generated functions.  So in general, this patch will lead to crashes due to races.

The problems with C constructors listed above are not relevant to Orc.
Comment 5 Tim-Philipp Müller 2015-08-25 21:56:33 UTC
(In reply to David Schleef from comment #4)
> 
> The problems with C constructors listed above are not relevant to Orc.

Could you elaborate what you mean by that? Clearly it's relevant to some use cases..
Comment 6 Nirbheek Chauhan 2015-08-26 03:47:10 UTC
(In reply to David Schleef from comment #4)
> Calling orc_init() is not required in order to use orc-generated functions. 
> So in general, this patch will lead to crashes due to races.
> 

This is not entirely correct. With this patch, if you do not call orc_init(), the critical sections will not be initialized and your program will immediately segfault when *_mutex_lock is called.

> The problems with C constructors listed above are not relevant to Orc.

Well, I wrote this patch specifically because of a use-case that I encountered. :) Allow me to elaborate.

This patch is only relevant on Windows since pthread mutexes don't need to be initialized at runtime.

The code had a toolchain-dependant implementation of C constructors, which meant that if you linked a liborc static library created with MinGW inside a project that was built and linked with MSVC, the C constructor would not be called at all, the CS would not be initialized, and your code would segfault as soon as orc called *_mutex_lock.

Orc does build on MSVC, but the build system does not allow it and there's no MSVC binaries available. There are, however, MinGW binaries available.

Also, unlike GNU C constructors, there is no way to guarantee the order in which MSVC C constructors are called, so using orc functions inside your program's C constructor was impossible.

Finally, using C constructors this way on MSVC is an undocumented hack that might continue to be supported by MSVC because lots of people use it, but is actually an internal compiler feature for implementing global initializers: https://msdn.microsoft.com/en-us/library/bb918180.aspx

Going back to...

> Calling orc_init() is not required in order to use orc-generated functions. 

I wasn't aware of this. :) Why does that function exist at all then? Or do you mean that a subset of orc can be used without calling orc_init()? I couldn't find information about this in the docs.

If orc_init() is indeed optional, we could just do both things. Keep the C constructor and also initialize inside orc_init(). That way all use cases will keep working. The overhead is the checking of one volatile int via a memory barrier at program load, which is negligible.
Comment 7 Nirbheek Chauhan 2015-10-12 23:08:27 UTC
FWIW, it seems using C constructors causes problems with Windows 10. See bug 752837. We should almost certainly move away from using it.
Comment 8 GStreamer system administrator 2018-11-03 10:48:04 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/orc/issues/10.