[sr-dev] git:master: shm_regex lib: locks added around the regular expression

Miklos Tirpak miklos at iptel.org
Mon Jun 14 15:47:38 CEST 2010


Module: sip-router
Branch: master
Commit: fc28a62a4ef4ff2eaa9e1636a747099284280a23
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=fc28a62a4ef4ff2eaa9e1636a747099284280a23

Author: Miklos Tirpak <miklos at iptel.org>
Committer: Miklos Tirpak <miklos at iptel.org>
Date:   Mon Jun 14 15:40:20 2010 +0200

shm_regex lib: locks added around the regular expression

The libc locks moved to shared memory did not work on
multi-cpu machines.
Credit goes to Stefan Keller (stefan.keller at isaco.de) for
identifying the problem and for the patch.

"The code hangs in regexec() when trying to acquire the lock.
... 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 Lucid)."

---

 lib/shm_regex/Makefile    |    1 +
 lib/shm_regex/shm_regex.c |   35 +++++++++++++++++++++++++++--------
 lib/shm_regex/shm_regex.h |   18 +++++++++++++-----
 3 files changed, 41 insertions(+), 13 deletions(-)

diff --git a/lib/shm_regex/Makefile b/lib/shm_regex/Makefile
index 2a0c907..4653863 100644
--- a/lib/shm_regex/Makefile
+++ b/lib/shm_regex/Makefile
@@ -8,6 +8,7 @@ NAME:=ser_shm_regex
 MAJOR_VER=0
 MINOR_VER=1
 BUGFIX_VER=0
+INCLUDES= -I$(CURDIR)/../..
 LIBS=
 
 include ../../Makefile.libs
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 */




More information about the sr-dev mailing list