Hi, I used the shm_regex functions from lib in one of my own modules and noticed that it is dead-locking (it hangs in FUTEX_WAIT). The code hangs in regexec() when trying to acquire the lock. This was a bit hard to find out as I couldn't reproduce it in a virtual machine with some test code I wrote. It turns out this only happens if the machine has more than one physical CPU core. Reproducable on x86_64 with two CPU cores, glibc 2.3.6 (from Debian Etch) and glibc 2.11.1 (from Ubuntu Jaunty). Attached is a patch which does its own locking and thus works around this problem.
Best regards, Stefan -- M.Eng. Stefan Keller CTO (Technischer Leiter) Phone +49-30-203899889 Mobile +49-170-4150437 Fax +49-30-722399150 [email protected] www.isaco.de ISACO GmbH Kurfürstenstr. 79 10787 Berlin Germany Amtsgericht Charlottenburg, HRB 112464B Geschäftsführer: Daniel Frommherz
From 19c32c5bb8b9e369007db99d541793234608d480 Mon Sep 17 00:00:00 2001 From: Stefan Keller <[email protected]> Date: Tue, 8 Jun 2010 17:26:46 +0200 Subject: [PATCH] work-around libc's regex deadlock - libc's regexec() deadlocks with multiple cores and shm - using own per-regex locking works-around this --- lib/shm_regex/shm_regex.c | 35 +++++++++++++++++++++++++++-------- lib/shm_regex/shm_regex.h | 18 +++++++++++++----- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lib/shm_regex/shm_regex.c b/lib/shm_regex/shm_regex.c index 165d535..e28d1c9 100644 --- a/lib/shm_regex/shm_regex.c +++ b/lib/shm_regex/shm_regex.c @@ -27,6 +27,8 @@ * History * ------- * 2009-04-03 Initial version (Miklos) + * 2010-04-25 Use own struct with locking to work-around libc locking failure + * on multi-core hw (skeller) */ #include <malloc.h> /* hook prototypes */ @@ -75,32 +77,37 @@ static void shm_free_hook(void *ptr, const void *caller) __free_hook = orig_free_hook; \ } while (0) -int shm_regcomp(regex_t *preg, const char *regex, int cflags) +int shm_regcomp(shm_regex_t *preg, const char *regex, int cflags) { malloc_hook_t *orig_malloc_hook; realloc_hook_t *orig_realloc_hook; free_hook_t *orig_free_hook; int ret; + if(!lock_init(&preg->lock)) { + return REG_EEND; + } replace_malloc_hooks(); - ret = regcomp(preg, regex, cflags); + ret = regcomp(&preg->regexp, regex, cflags); restore_malloc_hooks(); + if(ret) lock_destroy(&preg->lock); + return ret; } -void shm_regfree(regex_t *preg) +void shm_regfree(shm_regex_t *preg) { malloc_hook_t *orig_malloc_hook; realloc_hook_t *orig_realloc_hook; free_hook_t *orig_free_hook; - + lock_destroy(&preg->lock); replace_malloc_hooks(); - regfree(preg); + regfree(&preg->regexp); restore_malloc_hooks(); } -int shm_regexec(const regex_t *preg, const char *string, size_t nmatch, +int shm_regexec(shm_regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) { malloc_hook_t *orig_malloc_hook; @@ -118,12 +125,24 @@ int shm_regexec(const regex_t *preg, const char *string, size_t nmatch, * It is safe to call regexec() concurrently without locking, * because regexec() has its own locks. * (Miklos) + * + * Those locks, however, don't work with shm and multi-core hardware + * causing a dead-lock. Tested with glibc 2.3.6. (skeller) */ + + lock_get(&preg->lock); replace_malloc_hooks(); - ret = regexec(preg, string, nmatch, + ret = regexec(&preg->regexp, string, nmatch, pmatch, eflags); restore_malloc_hooks(); - + lock_release(&preg->lock); + return ret; } +size_t shm_regerror(int errcode, const shm_regex_t *preg, char *errbuf, + size_t errbuf_size) +{ + return regerror(errcode, &preg->regexp, errbuf, errbuf_size); +} + diff --git a/lib/shm_regex/shm_regex.h b/lib/shm_regex/shm_regex.h index 42ec52b..aabf100 100644 --- a/lib/shm_regex/shm_regex.h +++ b/lib/shm_regex/shm_regex.h @@ -27,6 +27,8 @@ * History * ------- * 2009-04-03 Initial version (Miklos) + * 2010-04-25 Use own struct with locking to work-around libc locking failure + * on multi-core hw (skeller) */ #ifndef _SHM_REGEX_H @@ -34,12 +36,18 @@ #include <sys/types.h> #include <regex.h> +#include "locking.h" -int shm_regcomp(regex_t *preg, const char *regex, int cflags); -void shm_regfree(regex_t *preg); -int shm_regexec(const regex_t *preg, const char *string, size_t nmatch, - regmatch_t pmatch[], int eflags); +typedef struct shm_regex { + regex_t regexp; + gen_lock_t lock; +} shm_regex_t; -#define shm_regerror regerror +int shm_regcomp(shm_regex_t *preg, const char *regex, int cflags); +void shm_regfree(shm_regex_t *preg); +int shm_regexec(shm_regex_t *preg, const char *string, size_t nmatch, + regmatch_t pmatch[], int eflags); +size_t shm_regerror(int errcode, const shm_regex_t *preg, char *errbuf, + size_t errbuf_size); #endif /* _SHM_REGEX_H */ -- 1.7.0.4
signature.asc
Description: PGP signature
_______________________________________________ sr-dev mailing list [email protected] http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
