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 613943 - Native regex literal compilation should be guarded by g_once_init_enter/leave
Native regex literal compilation should be guarded by g_once_init_enter/leave
Status: RESOLVED FIXED
Product: vala
Classification: Core
Component: general
unspecified
Other Linux
: Normal major
: ---
Assigned To: Vala maintainers
Vala maintainers
Depends on:
Blocks:
 
 
Reported: 2010-03-25 19:21 UTC by Sebastian Dröge (slomo)
Modified: 2010-03-31 19:41 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Thread safe regex literal initialization (partial) (1.75 KB, patch)
2010-03-25 21:28 UTC, Jukka-Pekka Iivonen
none Details | Review
Regular expression thread safety fix (3.83 KB, patch)
2010-03-26 10:03 UTC, Jukka-Pekka Iivonen
none Details | Review
Thread safe regular expression literals (4.92 KB, patch)
2010-03-26 13:10 UTC, Jukka-Pekka Iivonen
none Details | Review

Description Sebastian Dröge (slomo) 2010-03-25 19:21:05 UTC
Hi,
currently the native regex literals are compiled into a static variable the first time they're used but unfortunately without making sure to do this in a threadsafe way.

The g_regex_new() call should be wrapped inside a g_once_init_enter() / g_once_init_leave() block to fix this. Using the same compiled regex from different threads at the same time seems to work fine fortunately (according to the GLib docs at least) so we don't need any mutexes at least :)
Comment 1 Sebastian Dröge (slomo) 2010-03-25 19:22:20 UTC
Note that using g_once_init_enter/leave for pointers is no problem although it takes gsize as parameter. gsize should be of the same size as a pointer.
Comment 2 Jukka-Pekka Iivonen 2010-03-25 20:09:50 UTC
So the following initialization would be thread safe:


    static GRegex* _safe_regex_init (GRegex* re, gchar* pattern, GRegexMatchFlags match_options)
    {
	if (g_once_init_enter ((volatile gsize*) &re)) {
		GRegex* val = g_regex_new (pattern, match_options, 0, NULL);
		g_once_init_leave ((volatile gsize *) &re, (gsize) val);
	}

	return re;
    }

And then in the code where regex is used:

    _tmp0_regex0 = _safe_regex_init (_tmp_regex_0, "myregex", 0)


I'll try to create a patch to generate it this way.
Comment 3 Sebastian Dröge (slomo) 2010-03-25 20:20:02 UTC
No, that won't work this way. This is better:

static inline GRegex* _safe_regex_init (GRegex** re, const gchar* pattern,
GRegexMatchFlags match_options)
{
    if (g_once_init_enter ((volatile gsize*) *re)) {
        GRegex* val = g_regex_new (pattern, match_options, 0, NULL);
        g_once_init_leave ((volatile gsize *) *re, (gsize) val);
    }

    return *re;
}


_tmp_regex_0 = _safe_regex_init (&_tmp_regex_0_storage, "myregex", 0);

Note that you should never assign a new value to the storage of the GRegex after the initialization because setting a pointer could be non-atomic on some architectures!
Comment 4 Jukka-Pekka Iivonen 2010-03-25 20:43:26 UTC
This seems to work. The upper one seg.faults.


static inline GRegex* _thread_safe_regex_init (GRegex** re, const gchar* pattern,
GRegexMatchFlags match_options)
{
    if (g_once_init_enter ((volatile gsize*) re)) {
        GRegex* val = g_regex_new (pattern, match_options, 0, NULL);
        g_once_init_leave ((volatile gsize *) re, (gsize) val);
    }

    return *re;
}
Comment 5 Sebastian Dröge (slomo) 2010-03-25 20:47:00 UTC
Err, yes. Your last version is correct :)
Comment 6 Jukka-Pekka Iivonen 2010-03-25 21:28:03 UTC
Created attachment 157113 [details] [review]
Thread safe regex literal initialization (partial)

The attached patch should fix the problem once I found out (or someone gives me a hint) how to append the _thread_safe_regex_init function to the C code.
Comment 7 Jukka-Pekka Iivonen 2010-03-26 10:03:28 UTC
Created attachment 157146 [details] [review]
Regular expression thread safety fix

This fixes the issue. I created a new class for raw C code nodes.
Comment 8 Sebastian Dröge (slomo) 2010-03-26 11:59:44 UTC
I think it's preferred to add the function not as a single blob but by using the CCode stuff for all parts of the function. This way you automatically get correct indention and everything.
Comment 9 Sebastian Dröge (slomo) 2010-03-26 12:02:23 UTC
Classes to look at are CCodeFunction (for the function declaration including return type and parameters and flags... and the body), CCodeConditionalExpression, CCodeFunctionCall, CCodeAssignment.

Look at codegen/valatyperegisterfunction.vala for an example of a g_once_init_enter/leave block.
Comment 10 Jukka-Pekka Iivonen 2010-03-26 13:10:30 UTC
Created attachment 157159 [details] [review]
Thread safe regular expression literals

How about this?
Comment 11 Sebastian Dröge (slomo) 2010-03-26 13:30:45 UTC
Yes, the generated code looks good and your patch looks good to me too :)

IIRC there's something for CCodeIdentifier ("GRegex* val"), CCodeVariableDeclaration or something and something else for casts too and pointer dereferences but I don't think it's that important.
Comment 12 Sebastian Dröge (slomo) 2010-03-27 14:03:54 UTC
Oh another thing, you might want to store the compiled GRegex in a static variable inside the function scope instead of making it global. That might make it easier to prevent identifier collisions.
Comment 13 Jürg Billeter 2010-03-31 19:41:19 UTC
commit 0ea081ce7c654fe2fc88709884ec612f3d815687
Author: Jukka-Pekka Iivonen <jp0409@jippii.fi>
Date:   Wed Mar 31 21:38:01 2010 +0200

    Use thread-safe initialization for regular expression literals
    
    Fixes bug 613943.