List:Internals« Previous MessageNext Message »
From:Jeremy Zawodny Date:October 18 2002 6:20pm
Subject:[PATCH] mysys/my_symlink.c -- realpath() not thread-safe on FreeBSD.
View as plain text  
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
Thread
[PATCH] mysys/my_symlink.c -- realpath() not thread-safe on FreeBSD.Jeremy Zawodny18 Oct
  • [PATCH] mysys/my_symlink.c -- realpath() not thread-safe on FreeBSD.Michael Widenius20 Oct
    • Re: [PATCH] mysys/my_symlink.c -- realpath() not thread-safe on FreeBSD.Jeremy Zawodny20 Oct