Hi Monty & others,
We've *finally* tracked down a mysterious MySQL problem that has been
affecting some of our FreeBSD/MySQL/LinuxThreads servers. It turns
out that FreeBSD's realpath() isn't thread-safe. The result is that
you can have two processes both changing the current working directory
(realpath() does a a chdir() behind the scenes) on a shared file
descriptor and tries to restore it later and leaving the file
descriptor in an improper state. It's a simple race condition.
This doesn't *seem* to affect MySQL using FreeBSD's native threads,
because they are not pre-emptive or SMP aware. In order to use SMP,
we often build MySQL with LinuxThreads. The performance is excellent
this way.
The attached patch (below my sig) is *our* fix. A proper patch should
only implement the mutex on FreeBSD and probably omit the warning that
we added. Given how infrequently my_realpath() is called, it's
probably not worth making it specific to FreeBSD/LinuxThreads--but
that's obviously your decision.
Could something appropriate be applied to at least the 4.0 and 4.1
trees? I'm running this patch in production on MySQL 4.0.5.
A big thanks goes to Rick Reed at Yahoo for helping me to track this
down.
Jeremy
--
Jeremy D. Zawodny | Perl, Web, MySQL, Linux Magazine, Yahoo!
<Jeremy@stripped> | http://jeremy.zawodny.com/
MySQL 3.23.51: up 73 days, processed 1,552,723,378 queries (244/sec. avg)
--- my_symlink.c-orig Thu Oct 17 10:16:34 2002
+++ my_symlink.c Thu Oct 17 10:35:33 2002
@@ -115,6 +115,12 @@
(!lstat(filename,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
{
char *ptr;
+#ifdef THREAD
+ if (pthread_mutex_trylock(&THR_LOCK_open)) {
+ printf("[Yahoo!] my_realpath(%s) re-entered\n",filename);
+ pthread_mutex_lock(&THR_LOCK_open);
+ }
+#endif
DBUG_PRINT("info",("executing realpath"));
if ((ptr=realpath(filename,buff)))
{
@@ -131,6 +137,9 @@
strmov(to,filename);
result= -1;
}
+#ifdef THREAD
+ pthread_mutex_unlock(&THR_LOCK_open);
+#endif
}
DBUG_RETURN(result);
#else