summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mysql.com>2008-10-21 21:31:14 +0200
committerSergei Golubchik <serg@mysql.com>2008-10-21 21:31:14 +0200
commit1033d8fd93c34a62fb7cefd368ccc43c00fc0ec4 (patch)
tree04a659478a302313b6326dec32570bdfe70a211a /mysys
parenta58d20053dbd9192905bb4525f089a32f16b88f5 (diff)
parentd40f3fc3b82a5abccad2514696d774e10df70a32 (diff)
downloadmariadb-git-1033d8fd93c34a62fb7cefd368ccc43c00fc0ec4.tar.gz
merged
Diffstat (limited to 'mysys')
-rw-r--r--[-rwxr-xr-x]mysys/CMakeLists.txt2
-rw-r--r--mysys/Makefile.am2
-rw-r--r--mysys/default.c267
-rw-r--r--mysys/errors.c2
-rw-r--r--mysys/mf_pack.c81
-rw-r--r--mysys/my_alloc.c2
-rw-r--r--mysys/my_static.c4
-rw-r--r--mysys/my_symlink.c55
-rw-r--r--mysys/my_uuid.c65
-rw-r--r--mysys/safemalloc.c56
-rw-r--r--mysys/stacktrace.c584
-rw-r--r--mysys/thr_lock.c2
12 files changed, 891 insertions, 231 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
index ea71eb208dc..8552eae3974 100755..100644
--- a/mysys/CMakeLists.txt
+++ b/mysys/CMakeLists.txt
@@ -39,7 +39,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c default_
my_mkdir.c my_mmap.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c
my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_sleep.c
my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c
- my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c
+ my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c stacktrace.c
rijndael.c safemalloc.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c
thr_rwlock.c tree.c typelib.c my_vle.c base64.c my_memmem.c my_getpagesize.c
lf_alloc-pin.c lf_dynarray.c lf_hash.c
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index d4c36d86dbe..e5e7539ece6 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -54,7 +54,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
charset.c charset-def.c my_bitmap.c my_bit.c md5.c \
my_gethostbyname.c rijndael.c my_aes.c sha1.c \
my_handler.c my_netware.c my_largepage.c \
- my_memmem.c \
+ my_memmem.c stacktrace.c \
my_windac.c my_access.c base64.c my_libwrap.c \
wqueue.c
if THREAD
diff --git a/mysys/default.c b/mysys/default.c
index 2758029ec12..6b2b31d43ec 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -48,13 +48,12 @@ char *my_defaults_extra_file=0;
/* Which directories are searched for options (and in which order) */
#define MAX_DEFAULT_DIRS 6
-const char *default_directories[MAX_DEFAULT_DIRS + 1];
+#define DEFAULT_DIRS_SIZE (MAX_DEFAULT_DIRS + 1) /* Terminate with NULL */
+static const char **default_directories = NULL;
#ifdef __WIN__
static const char *f_extensions[]= { ".ini", ".cnf", 0 };
#define NEWLINE "\r\n"
-static char system_dir[FN_REFLEN], shared_system_dir[FN_REFLEN],
- config_dir[FN_REFLEN];
#else
static const char *f_extensions[]= { ".cnf", 0 };
#define NEWLINE "\n"
@@ -85,19 +84,34 @@ static int search_default_file_with_ext(Process_option_func func,
const char *config_file, int recursion_level);
-
/**
Create the list of default directories.
+ @param alloc MEM_ROOT where the list of directories is stored
+
@details
+ The directories searched, in order, are:
+ - Windows: GetSystemWindowsDirectory()
+ - Windows: GetWindowsDirectory()
+ - Windows: C:/
+ - Windows: Directory above where the executable is located
+ - Netware: sys:/etc/
+ - Unix: /etc/
+ - Unix: /etc/mysql/
+ - Unix: --sysconfdir=<path> (compile-time option)
+ - ALL: getenv(DEFAULT_HOME_ENV)
+ - ALL: --defaults-extra-file=<path> (run-time option)
+ - Unix: ~/
+
On all systems, if a directory is already in the list, it will be moved
to the end of the list. This avoids reading defaults files multiple times,
while ensuring the correct precedence.
- @return void
+ @retval NULL Failure (out of memory, probably)
+ @retval other Pointer to NULL-terminated array of default directories
*/
-static void (*init_default_directories)();
+static const char **init_default_directories(MEM_ROOT *alloc);
static char *remove_end_comment(char *ptr);
@@ -390,8 +404,9 @@ int load_defaults(const char *conf_file, const char **groups,
struct handle_option_ctx ctx;
DBUG_ENTER("load_defaults");
- init_default_directories();
init_alloc_root(&alloc,512,0);
+ if ((default_directories= init_default_directories(&alloc)) == NULL)
+ goto err;
/*
Check if the user doesn't want any default option processing
--no-defaults is always the first option
@@ -873,34 +888,49 @@ void my_print_default_files(const char *conf_file)
my_bool have_ext= fn_ext(conf_file)[0] != 0;
const char **exts_to_use= have_ext ? empty_list : f_extensions;
char name[FN_REFLEN], **ext;
- const char **dirs;
- init_default_directories();
puts("\nDefault options are read from the following files in the given order:");
if (dirname_length(conf_file))
fputs(conf_file,stdout);
else
{
- for (dirs=default_directories ; *dirs; dirs++)
+ /*
+ If default_directories is already initialized, use it. Otherwise,
+ use a private MEM_ROOT.
+ */
+ const char **dirs = default_directories;
+ MEM_ROOT alloc;
+ init_alloc_root(&alloc,512,0);
+
+ if (!dirs && (dirs= init_default_directories(&alloc)) == NULL)
+ {
+ fputs("Internal error initializing default directories list", stdout);
+ }
+ else
{
- for (ext= (char**) exts_to_use; *ext; ext++)
+ for ( ; *dirs; dirs++)
{
- const char *pos;
- char *end;
- if (**dirs)
- pos= *dirs;
- else if (my_defaults_extra_file)
- pos= my_defaults_extra_file;
- else
- continue;
- end= convert_dirname(name, pos, NullS);
- if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
- *end++='.';
- strxmov(end, conf_file, *ext, " ", NullS);
- fputs(name,stdout);
+ for (ext= (char**) exts_to_use; *ext; ext++)
+ {
+ const char *pos;
+ char *end;
+ if (**dirs)
+ pos= *dirs;
+ else if (my_defaults_extra_file)
+ pos= my_defaults_extra_file;
+ else
+ continue;
+ end= convert_dirname(name, pos, NullS);
+ if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
+ *end++= '.';
+ strxmov(end, conf_file, *ext, " ", NullS);
+ fputs(name, stdout);
+ }
}
}
+
+ free_root(&alloc, MYF(0));
}
puts("");
}
@@ -937,32 +967,22 @@ void print_defaults(const char *conf_file, const char **groups)
#include <help_end.h>
-/*
- This extra complexity is to avoid declaring 'rc' if it won't be
- used.
-*/
-#define ADD_DIRECTORY_INTERNAL(DIR) \
- array_append_string_unique((DIR), default_directories, \
- array_elements(default_directories))
-#ifdef DBUG_OFF
-# define ADD_DIRECTORY(DIR) (void) ADD_DIRECTORY_INTERNAL(DIR)
-#else
-#define ADD_DIRECTORY(DIR) \
- do { \
- my_bool rc= ADD_DIRECTORY_INTERNAL(DIR); \
- DBUG_ASSERT(rc == FALSE); /* Success */ \
- } while (0)
-#endif
-
+static int add_directory(MEM_ROOT *alloc, const char *dir, const char **dirs)
+{
+ char buf[FN_REFLEN];
+ uint len;
+ char *p;
+ my_bool err __attribute__((unused));
+
+ len= normalize_dirname(buf, dir);
+ if (!(p= strmake_root(alloc, buf, len)))
+ return 1; /* Failure */
+ /* Should never fail if DEFAULT_DIRS_SIZE is correct size */
+ err= array_append_string_unique(p, dirs, DEFAULT_DIRS_SIZE);
+ DBUG_ASSERT(err == FALSE);
-#define ADD_COMMON_DIRECTORIES() \
- do { \
- char *env; \
- if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) \
- ADD_DIRECTORY(env); \
- /* Placeholder for --defaults-extra-file=<path> */ \
- ADD_DIRECTORY(""); \
- } while (0)
+ return 0;
+}
#ifdef __WIN__
@@ -1001,115 +1021,90 @@ static size_t my_get_system_windows_directory(char *buffer, size_t size)
}
-/**
- Initialize default directories for Microsoft Windows
-
- @details
- 1. GetSystemWindowsDirectory()
- 2. GetWindowsDirectory()
- 3. C:/
- 4. Directory above where the executable is located
- 5. getenv(DEFAULT_HOME_ENV)
- 6. --defaults-extra-file=<path> (run-time option)
-*/
-
-static void init_default_directories_win()
+static const char *my_get_module_parent(char *buf, size_t size)
{
- bzero((char *) default_directories, sizeof(default_directories));
-
- if (my_get_system_windows_directory(shared_system_dir,
- sizeof(shared_system_dir)))
- ADD_DIRECTORY(shared_system_dir);
-
- if (GetWindowsDirectory(system_dir,sizeof(system_dir)))
- ADD_DIRECTORY(system_dir);
-
- ADD_DIRECTORY("C:/");
+ char *last= NULL;
+ char *end;
+ if (!GetModuleFileName(NULL, buf, (DWORD) size))
+ return NULL;
+ end= strend(buf);
- if (GetModuleFileName(NULL, config_dir, sizeof(config_dir)))
+ /*
+ Look for the second-to-last \ in the filename, but hang on
+ to a pointer after the last \ in case we're in the root of
+ a drive.
+ */
+ for ( ; end > buf; end--)
{
- char *last= NULL, *end= strend(config_dir);
- /*
- Look for the second-to-last \ in the filename, but hang on
- to a pointer after the last \ in case we're in the root of
- a drive.
- */
- for ( ; end > config_dir; end--)
+ if (*end == FN_LIBCHAR)
{
- if (*end == FN_LIBCHAR)
+ if (last)
{
- if (last)
- {
- if (end != config_dir)
- {
- /* Keep the last '\' as this works both with D:\ and a directory */
- end[1]= 0;
- }
- else
- {
- /* No parent directory (strange). Use current dir + '\' */
- last[1]= 0;
- }
- break;
- }
- last= end;
+ /* Keep the last '\' as this works both with D:\ and a directory */
+ end[1]= 0;
+ break;
}
+ last= end;
}
- ADD_DIRECTORY(config_dir);
}
- ADD_COMMON_DIRECTORIES();
+ return buf;
}
+#endif /* __WIN__ */
-static void (*init_default_directories)()= init_default_directories_win;
-#elif defined(__NETWARE__)
+static const char **init_default_directories(MEM_ROOT *alloc)
+{
+ const char **dirs;
+ char *env;
+ int errors= 0;
-/**
- Initialize default directories for Novell Netware
+ dirs= (const char **)alloc_root(alloc, DEFAULT_DIRS_SIZE * sizeof(char *));
+ if (dirs == NULL)
+ return NULL;
+ bzero((char *) dirs, DEFAULT_DIRS_SIZE * sizeof(char *));
- @details
- 1. sys:/etc/
- 2. getenv(DEFAULT_HOME_ENV)
- 3. --defaults-extra-file=<path> (run-time option)
-*/
+#ifdef __WIN__
-static void init_default_directories_netware()
-{
- bzero((char *) default_directories, sizeof(default_directories));
- ADD_DIRECTORY("sys:/etc/");
- ADD_COMMON_DIRECTORIES();
-}
+ {
+ char fname_buffer[FN_REFLEN];
+ if (my_get_system_windows_directory(fname_buffer, sizeof(fname_buffer)))
+ errors += add_directory(alloc, fname_buffer, dirs);
-static void (*init_default_directories)()= init_default_directories_netware;
+ if (GetWindowsDirectory(fname_buffer, sizeof(fname_buffer)))
+ errors += add_directory(alloc, fname_buffer, dirs);
-#else
+ errors += add_directory(alloc, "C:/", dirs);
-/**
- Initialize default directories for Unix
+ if (my_get_module_parent(fname_buffer, sizeof(fname_buffer)) != NULL)
+ errors += add_directory(alloc, fname_buffer, dirs);
+ }
- @details
- 1. /etc/
- 2. /etc/mysql/
- 3. --sysconfdir=<path> (compile-time option)
- 4. getenv(DEFAULT_HOME_ENV)
- 5. --defaults-extra-file=<path> (run-time option)
- 6. "~/"
-*/
+#elif defined(__NETWARE__)
-static void init_default_directories_unix()
-{
- bzero((char *) default_directories, sizeof(default_directories));
- ADD_DIRECTORY("/etc/");
- ADD_DIRECTORY("/etc/mysql/");
-#ifdef DEFAULT_SYSCONFDIR
+ errors += add_directory(alloc, "sys:/etc/", dirs);
+
+#else
+
+ errors += add_directory(alloc, "/etc/", dirs);
+ errors += add_directory(alloc, "/etc/mysql/", dirs);
+
+#if defined(DEFAULT_SYSCONFDIR)
if (DEFAULT_SYSCONFDIR != "")
- ADD_DIRECTORY(DEFAULT_SYSCONFDIR);
+ errors += add_directory(alloc, DEFAULT_SYSCONFDIR, dirs);
+#endif /* DEFAULT_SYSCONFDIR */
+
#endif
- ADD_COMMON_DIRECTORIES();
- ADD_DIRECTORY("~/");
-}
-static void (*init_default_directories)()= init_default_directories_unix;
+ if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV))))
+ errors += add_directory(alloc, env, dirs);
+ /* Placeholder for --defaults-extra-file=<path> */
+ errors += add_directory(alloc, "", dirs);
+
+#if !defined(__WIN__) && !defined(__NETWARE__)
+ errors += add_directory(alloc, "~/", dirs);
#endif
+
+ return (errors > 0 ? NULL : dirs);
+}
diff --git a/mysys/errors.c b/mysys/errors.c
index db63667fb77..3c690ed5ca4 100644
--- a/mysys/errors.c
+++ b/mysys/errors.c
@@ -76,7 +76,7 @@ void init_glob_errs()
EE(EE_STAT) = "Can't get stat of '%s' (Errcode: %d)";
EE(EE_CANT_CHSIZE) = "Can't change size of file (Errcode: %d)";
EE(EE_CANT_OPEN_STREAM)= "Can't open stream from handle (Errcode: %d)";
- EE(EE_GETWD) = "Can't get working dirctory (Errcode: %d)";
+ EE(EE_GETWD) = "Can't get working directory (Errcode: %d)";
EE(EE_SETWD) = "Can't change dir to '%s' (Errcode: %d)";
EE(EE_LINK_WARNING) = "Warning: '%s' had %d links";
EE(EE_OPEN_WARNING) = "Warning: %d files and %d streams is left open\n";
diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c
index 63525e4d927..d4828946d82 100644
--- a/mysys/mf_pack.c
+++ b/mysys/mf_pack.c
@@ -277,22 +277,64 @@ void symdirget(char *dir)
#endif /* USE_SYMDIR */
-/*
- Fixes a directroy name so that can be used by open()
+/**
+ Convert a directory name to a format which can be compared as strings
- SYNOPSIS
- unpack_dirname()
- to result-buffer, FN_REFLEN characters. may be == from
- from 'Packed' directory name (may contain ~)
+ @param to result buffer, FN_REFLEN chars in length; may be == from
+ @param from 'packed' directory name, in whatever format
+ @returns size of the normalized name
- IMPLEMENTATION
- Make that last char of to is '/' if from not empty and
- from doesn't end in FN_DEVCHAR
- Uses cleanup_dirname and changes ~/.. to home_dir/..
+ @details
+ - Ensures that last char is FN_LIBCHAR, unless it is FN_DEVCHAR
+ - Uses cleanup_dirname
- Changes a UNIX filename to system filename (replaces / with \ on windows)
+ It does *not* expand ~/ (although, see cleanup_dirname). Nor does it do
+ any case folding. All case-insensitive normalization should be done by
+ the caller.
+*/
- RETURN
+size_t normalize_dirname(char *to, const char *from)
+{
+ size_t length;
+ char buff[FN_REFLEN];
+ DBUG_ENTER("normalize_dirname");
+
+ /*
+ Despite the name, this actually converts the name to the system's
+ format (TODO: rip out the non-working VMS stuff and name this
+ properly).
+ */
+ (void) intern_filename(buff, from);
+ length= strlen(buff); /* Fix that '/' is last */
+ if (length &&
+#ifdef FN_DEVCHAR
+ buff[length - 1] != FN_DEVCHAR &&
+#endif
+ buff[length - 1] != FN_LIBCHAR && buff[length - 1] != '/')
+ {
+ buff[length]= FN_LIBCHAR;
+ buff[length + 1]= '\0';
+ }
+
+ length=cleanup_dirname(to, buff);
+
+ DBUG_RETURN(length);
+}
+
+
+/**
+ Fixes a directory name so that can be used by open()
+
+ @param to Result buffer, FN_REFLEN characters. May be == from
+ @param from 'Packed' directory name (may contain ~)
+
+ @details
+ - Uses normalize_dirname()
+ - Expands ~/... to home_dir/...
+ - Resolves MySQL's fake "foo.sym" symbolic directory names (if USE_SYMDIR)
+ - Changes a UNIX filename to system filename (replaces / with \ on windows)
+
+ @returns
Length of new directory name (= length of to)
*/
@@ -302,19 +344,8 @@ size_t unpack_dirname(char * to, const char *from)
char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion;
DBUG_ENTER("unpack_dirname");
- (void) intern_filename(buff,from); /* Change to intern name */
- length= strlen(buff); /* Fix that '/' is last */
- if (length &&
-#ifdef FN_DEVCHAR
- buff[length-1] != FN_DEVCHAR &&
-#endif
- buff[length-1] != FN_LIBCHAR && buff[length-1] != '/')
- {
- buff[length]=FN_LIBCHAR;
- buff[length+1]= '\0';
- }
+ length= normalize_dirname(buff, from);
- length=cleanup_dirname(buff,buff);
if (buff[0] == FN_HOMELIB)
{
suffix=buff+1; tilde_expansion=expand_tilde(&suffix);
@@ -323,7 +354,7 @@ size_t unpack_dirname(char * to, const char *from)
length-= (size_t) (suffix-buff)-1;
if (length+(h_length= strlen(tilde_expansion)) <= FN_REFLEN)
{
- if (tilde_expansion[h_length-1] == FN_LIBCHAR)
+ if ((h_length > 0) && (tilde_expansion[h_length-1] == FN_LIBCHAR))
h_length--;
if (buff+h_length < suffix)
bmove(buff+h_length,suffix,length);
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index 9203ce9c34e..2607ea57d08 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -202,7 +202,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
{
if (mem_root->error_handler)
(*mem_root->error_handler)();
- return((void*) 0); /* purecov: inspected */
+ DBUG_RETURN((void*) 0); /* purecov: inspected */
}
mem_root->block_num++;
next->next= *prev;
diff --git a/mysys/my_static.c b/mysys/my_static.c
index a82c9bf518c..04bda8d2dcc 100644
--- a/mysys/my_static.c
+++ b/mysys/my_static.c
@@ -70,8 +70,8 @@ uint sf_malloc_prehunc=0, /* If you have problem with core- */
sf_malloc_endhunc=0, /* dump when malloc-message.... */
/* set theese to 64 or 128 */
sf_malloc_quick=0; /* set if no calls to sanity */
-ulong sf_malloc_cur_memory= 0L; /* Current memory usage */
-ulong sf_malloc_max_memory= 0L; /* Maximum memory usage */
+size_t sf_malloc_cur_memory= 0L; /* Current memory usage */
+size_t sf_malloc_max_memory= 0L; /* Maximum memory usage */
uint sf_malloc_count= 0; /* Number of times NEW() was called */
uchar *sf_min_adress= (uchar*) ~(unsigned long) 0L,
*sf_max_adress= (uchar*) 0L;
diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c
index 98059ccd508..f8c6ebf02c3 100644
--- a/mysys/my_symlink.c
+++ b/mysys/my_symlink.c
@@ -108,38 +108,47 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags)
#define BUFF_LEN FN_LEN
#endif
+
+int my_is_symlink(const char *filename __attribute__((unused)))
+{
+#if defined (HAVE_LSTAT) && defined (S_ISLNK)
+ struct stat stat_buff;
+ return !lstat(filename, &stat_buff) && S_ISLNK(stat_buff.st_mode);
+#elif defined (_WIN32)
+ DWORD dwAttr = GetFileAttributes(filename);
+ return (dwAttr != INVALID_FILE_ATTRIBUTES) &&
+ (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT);
+#else /* No symlinks */
+ return 0;
+#endif
+}
+
+
int my_realpath(char *to, const char *filename,
myf MyFlags __attribute__((unused)))
{
#if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH)
int result=0;
char buff[BUFF_LEN];
- struct stat stat_buff;
+ char *ptr;
DBUG_ENTER("my_realpath");
- if (!(MyFlags & MY_RESOLVE_LINK) ||
- (!lstat(filename,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
- {
- char *ptr;
- DBUG_PRINT("info",("executing realpath"));
- if ((ptr=realpath(filename,buff)))
- {
+ DBUG_PRINT("info",("executing realpath"));
+ if ((ptr=realpath(filename,buff)))
strmake(to,ptr,FN_REFLEN-1);
- }
- else
- {
- /*
- Realpath didn't work; Use my_load_path() which is a poor substitute
- original name but will at least be able to resolve paths that starts
- with '.'.
- */
- DBUG_PRINT("error",("realpath failed with errno: %d", errno));
- my_errno=errno;
- if (MyFlags & MY_WME)
- my_error(EE_REALPATH, MYF(0), filename, my_errno);
- my_load_path(to, filename, NullS);
- result= -1;
- }
+ else
+ {
+ /*
+ Realpath didn't work; Use my_load_path() which is a poor substitute
+ original name but will at least be able to resolve paths that starts
+ with '.'.
+ */
+ DBUG_PRINT("error",("realpath failed with errno: %d", errno));
+ my_errno=errno;
+ if (MyFlags & MY_WME)
+ my_error(EE_REALPATH, MYF(0), filename, my_errno);
+ my_load_path(to, filename, NullS);
+ result= -1;
}
DBUG_RETURN(result);
#else
diff --git a/mysys/my_uuid.c b/mysys/my_uuid.c
index d6a4946954a..d1e8331aaa1 100644
--- a/mysys/my_uuid.c
+++ b/mysys/my_uuid.c
@@ -58,7 +58,8 @@ pthread_mutex_t LOCK_uuid_generator;
1582-10-15 00:00:00.00 and 1970-01-01 00:00:00.00
*/
-#define UUID_TIME_OFFSET ((ulonglong) 141427 * 24 * 60 * 60 * 1000 * 10)
+#define UUID_TIME_OFFSET ((ulonglong) 141427 * 24 * 60 * 60 * \
+ 1000 * 1000 * 10)
#define UUID_VERSION 0x1000
#define UUID_VARIANT 0x8000
@@ -134,22 +135,64 @@ void my_uuid(uchar *to)
pthread_mutex_lock(&LOCK_uuid_generator);
tv= my_getsystime() + UUID_TIME_OFFSET + nanoseq;
- if (unlikely(tv < uuid_time))
- set_clock_seq();
- else if (unlikely(tv == uuid_time))
+
+ if (likely(tv > uuid_time))
{
- /* special protection for low-res system clocks */
- nanoseq++;
- tv++;
+ /*
+ Current time is ahead of last timestamp, as it should be.
+ If we "borrowed time", give it back, just as long as we
+ stay ahead of the previous timestamp.
+ */
+ if (nanoseq)
+ {
+ ulong delta;
+ DBUG_ASSERT((tv > uuid_time) && (nanoseq > 0));
+ /*
+ -1 so we won't make tv= uuid_time for nanoseq >= (tv - uuid_time)
+ */
+ delta= min(nanoseq, (ulong)(tv - uuid_time -1));
+ tv-= delta;
+ nanoseq-= delta;
+ }
}
else
{
- if (nanoseq && likely(tv-nanoseq >= uuid_time))
+ if (unlikely(tv == uuid_time))
{
- tv-=nanoseq;
- nanoseq=0;
+ /*
+ For low-res system clocks. If several requests for UUIDs
+ end up on the same tick, we add a nano-second to make them
+ different.
+ ( current_timestamp + nanoseq * calls_in_this_period )
+ may end up > next_timestamp; this is OK. Nonetheless, we'll
+ try to unwind nanoseq when we get a chance to.
+ If nanoseq overflows, we'll start over with a new numberspace
+ (so the if() below is needed so we can avoid the ++tv and thus
+ match the follow-up if() if nanoseq overflows!).
+ */
+ if (likely(++nanoseq))
+ ++tv;
+ }
+
+ if (unlikely(tv <= uuid_time))
+ {
+ /*
+ If the admin changes the system clock (or due to Daylight
+ Saving Time), the system clock may be turned *back* so we
+ go through a period once more for which we already gave out
+ UUIDs. To avoid duplicate UUIDs despite potentially identical
+ times, we make a new random component.
+ We also come here if the nanoseq "borrowing" overflows.
+ In either case, we throw away any nanoseq borrowing since it's
+ irrelevant in the new numberspace.
+ */
+ set_clock_seq();
+ tv= my_getsystime() + UUID_TIME_OFFSET;
+ nanoseq= 0;
+ DBUG_PRINT("uuid",("making new numberspace"));
}
}
+
uuid_time=tv;
pthread_mutex_unlock(&LOCK_uuid_generator);
@@ -185,7 +228,7 @@ void my_uuid2str(const uchar *guid, char *s)
{
*s++= _dig_vec_lower[guid[i] >>4];
*s++= _dig_vec_lower[guid[i] & 15];
- if(i == 4 || i == 6 || i == 8 || i == 10)
+ if(i == 3 || i == 5 || i == 7 || i == 9)
*s++= '-';
}
}
diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c
index 1ccfa213756..59bc4e73af7 100644
--- a/mysys/safemalloc.c
+++ b/mysys/safemalloc.c
@@ -151,9 +151,10 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags)
my_errno=errno;
sprintf(buff,"Out of memory at line %d, '%s'", lineno, filename);
my_message(EE_OUTOFMEMORY, buff, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH));
- sprintf(buff,"needed %u byte (%ldk), memory in use: %ld bytes (%ldk)",
- (uint) size, (uint) (size + 1023L) / 1024L,
- sf_malloc_max_memory, (sf_malloc_max_memory + 1023L) / 1024L);
+ sprintf(buff,"needed %lu byte (%luk), memory in use: %lu bytes (%luk)",
+ (ulong) size, (ulong) (size + 1023L) / 1024L,
+ (ulong) sf_malloc_max_memory,
+ (ulong) (sf_malloc_max_memory + 1023L) / 1024L);
my_message(EE_OUTOFMEMORY, buff, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH));
}
DBUG_PRINT("error",("Out of memory, in use: %ld at line %d, '%s'",
@@ -193,7 +194,7 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags)
if ((MyFlags & MY_ZEROFILL) || !sf_malloc_quick)
bfill(data, size, (char) (MyFlags & MY_ZEROFILL ? 0 : ALLOC_VAL));
/* Return a pointer to the real data */
- DBUG_PRINT("exit",("ptr: 0x%lx", (long) data));
+ DBUG_PRINT("exit",("ptr: %p", data));
if (sf_min_adress > data)
sf_min_adress= data;
if (sf_max_adress < data)
@@ -258,7 +259,7 @@ void _myfree(void *ptr, const char *filename, uint lineno, myf myflags)
{
struct st_irem *irem;
DBUG_ENTER("_myfree");
- DBUG_PRINT("enter",("ptr: 0x%lx", (long) ptr));
+ DBUG_PRINT("enter",("ptr: %p", ptr));
if (!sf_malloc_quick)
(void) _sanity (filename, lineno);
@@ -391,12 +392,12 @@ void TERMINATE(FILE *file, uint flag)
{
if (file)
{
- fprintf(file, "Warning: Memory that was not free'ed (%ld bytes):\n",
- sf_malloc_cur_memory);
+ fprintf(file, "Warning: Memory that was not free'ed (%lu bytes):\n",
+ (ulong) sf_malloc_cur_memory);
(void) fflush(file);
}
- DBUG_PRINT("safe",("Memory that was not free'ed (%ld bytes):",
- sf_malloc_cur_memory));
+ DBUG_PRINT("safe",("Memory that was not free'ed (%lu bytes):",
+ (ulong) sf_malloc_cur_memory));
while (irem)
{
char *data= (((char*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) +
@@ -404,29 +405,29 @@ void TERMINATE(FILE *file, uint flag)
if (file)
{
fprintf(file,
- "\t%6lu bytes at 0x%09lx, allocated at line %4u in '%s'",
- (ulong) irem->datasize, (long) data,
- irem->linenum, irem->filename);
+ "\t%6lu bytes at %p, allocated at line %4u in '%s'",
+ (ulong) irem->datasize, data, irem->linenum, irem->filename);
fprintf(file, "\n");
(void) fflush(file);
}
DBUG_PRINT("safe",
- ("%6lu bytes at 0x%09lx, allocated at line %4d in '%s'",
- (ulong) irem->datasize, (long) data,
- irem->linenum, irem->filename));
+ ("%6lu bytes at %p, allocated at line %4d in '%s'",
+ (ulong) irem->datasize,
+ data, irem->linenum, irem->filename));
irem= irem->next;
}
}
/* Report the memory usage statistics */
if (file && flag)
{
- fprintf(file, "Maximum memory usage: %ld bytes (%ldk)\n",
- sf_malloc_max_memory, (sf_malloc_max_memory + 1023L) / 1024L);
+ fprintf(file, "Maximum memory usage: %lu bytes (%luk)\n",
+ (ulong) sf_malloc_max_memory,
+ (ulong) (sf_malloc_max_memory + 1023L) / 1024L);
(void) fflush(file);
}
- DBUG_PRINT("safe",("Maximum memory usage: %ld bytes (%ldk)",
- sf_malloc_max_memory, (sf_malloc_max_memory + 1023L) /
- 1024L));
+ DBUG_PRINT("safe",("Maximum memory usage: %lu bytes (%luk)",
+ (ulong) sf_malloc_max_memory,
+ (ulong) (sf_malloc_max_memory + 1023L) /1024L));
pthread_mutex_unlock(&THR_LOCK_malloc);
DBUG_VOID_RETURN;
}
@@ -447,9 +448,8 @@ void sf_malloc_report_allocated(void *memory)
sf_malloc_prehunc);
if (data <= (char*) memory && (char*) memory <= data + irem->datasize)
{
- printf("%lu bytes at 0x%lx, allocated at line %u in '%s'\n",
- (ulong) irem->datasize, (long) data,
- irem->linenum, irem->filename);
+ printf("%lu bytes at %p, allocated at line %u in '%s'\n",
+ (ulong) irem->datasize, data, irem->linenum, irem->filename);
break;
}
}
@@ -472,8 +472,8 @@ static int _checkchunk(register struct st_irem *irem, const char *filename,
irem->filename, irem->linenum);
fprintf(stderr, " discovered at %s:%d\n", filename, lineno);
(void) fflush(stderr);
- DBUG_PRINT("safe",("Underrun at 0x%lx, allocated at %s:%d",
- (long) data, irem->filename, irem->linenum));
+ DBUG_PRINT("safe",("Underrun at %p, allocated at %s:%d",
+ data, irem->filename, irem->linenum));
flag=1;
}
@@ -488,10 +488,8 @@ static int _checkchunk(register struct st_irem *irem, const char *filename,
irem->filename, irem->linenum);
fprintf(stderr, " discovered at '%s:%d'\n", filename, lineno);
(void) fflush(stderr);
- DBUG_PRINT("safe",("Overrun at 0x%lx, allocated at %s:%d",
- (long) data,
- irem->filename,
- irem->linenum));
+ DBUG_PRINT("safe",("Overrun at %p, allocated at %s:%d",
+ data, irem->filename, irem->linenum));
flag=1;
}
return(flag);
diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c
new file mode 100644
index 00000000000..5b941bbd7d6
--- /dev/null
+++ b/mysys/stacktrace.c
@@ -0,0 +1,584 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* Workaround for Bug#32082: VOID redefinition on Win results in compile errors*/
+#define DONT_DEFINE_VOID 1
+
+#include <my_global.h>
+#include <my_stacktrace.h>
+
+#ifndef __WIN__
+#include <signal.h>
+#include <my_pthread.h>
+#include <m_string.h>
+#ifdef HAVE_STACKTRACE
+#include <unistd.h>
+#include <strings.h>
+
+#if HAVE_EXECINFO_H
+#include <execinfo.h>
+#endif
+
+#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end)
+
+static char *heap_start;
+
+#ifdef HAVE_BSS_START
+extern char *__bss_start;
+#endif
+
+void my_init_stacktrace()
+{
+#ifdef HAVE_BSS_START
+ heap_start = (char*) &__bss_start;
+#endif
+}
+
+void my_safe_print_str(const char* name, const char* val, int max_len)
+{
+ char *heap_end= (char*) sbrk(0);
+ fprintf(stderr, "%s at %p ", name, val);
+
+ if (!PTR_SANE(val))
+ {
+ fprintf(stderr, "is an invalid pointer\n");
+ return;
+ }
+
+ fprintf(stderr, "= ");
+ for (; max_len && PTR_SANE(val) && *val; --max_len)
+ fputc(*val++, stderr);
+ fputc('\n', stderr);
+}
+
+#if HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD)
+
+#if BACKTRACE_DEMANGLE
+
+char __attribute__ ((weak)) *my_demangle(const char *mangled_name, int *status)
+{
+ return NULL;
+}
+
+static void my_demangle_symbols(char **addrs, int n)
+{
+ int status, i;
+ char *begin, *end, *demangled;
+
+ for (i= 0; i < n; i++)
+ {
+ demangled= NULL;
+ begin= strchr(addrs[i], '(');
+ end= begin ? strchr(begin, '+') : NULL;
+
+ if (begin && end)
+ {
+ *begin++= *end++= '\0';
+ demangled= my_demangle(begin, &status);
+ if (!demangled || status)
+ {
+ demangled= NULL;
+ begin[-1]= '(';
+ end[-1]= '+';
+ }
+ }
+
+ if (demangled)
+ fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end);
+ else
+ fprintf(stderr, "%s\n", addrs[i]);
+ }
+}
+
+#endif /* BACKTRACE_DEMANGLE */
+
+void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
+{
+ void *addrs[128];
+ char **strings= NULL;
+ int n = backtrace(addrs, array_elements(addrs));
+ fprintf(stderr, "stack_bottom = %p thread_stack 0x%lx\n",
+ stack_bottom, thread_stack);
+#if BACKTRACE_DEMANGLE
+ if ((strings= backtrace_symbols(addrs, n)))
+ {
+ my_demangle_symbols(strings, n);
+ free(strings);
+ }
+#endif
+#if HAVE_BACKTRACE_SYMBOLS_FD
+ if (!strings)
+ {
+ backtrace_symbols_fd(addrs, n, fileno(stderr));
+ }
+#endif
+}
+
+#elif defined(TARGET_OS_LINUX)
+
+#ifdef __i386__
+#define SIGRETURN_FRAME_OFFSET 17
+#endif
+
+#ifdef __x86_64__
+#define SIGRETURN_FRAME_OFFSET 23
+#endif
+
+#if defined(__alpha__) && defined(__GNUC__)
+/*
+ The only way to backtrace without a symbol table on alpha
+ is to find stq fp,N(sp), and the first byte
+ of the instruction opcode will give us the value of N. From this
+ we can find where the old value of fp is stored
+*/
+
+#define MAX_INSTR_IN_FUNC 10000
+
+inline uchar** find_prev_fp(uint32* pc, uchar** fp)
+{
+ int i;
+ for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
+ {
+ uchar* p = (uchar*)pc;
+ if (p[2] == 222 && p[3] == 35)
+ {
+ return (uchar**)((uchar*)fp - *(short int*)p);
+ }
+ }
+ return 0;
+}
+
+inline uint32* find_prev_pc(uint32* pc, uchar** fp)
+{
+ int i;
+ for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
+ {
+ char* p = (char*)pc;
+ if (p[1] == 0 && p[2] == 94 && p[3] == -73)
+ {
+ uint32* prev_pc = (uint32*)*((fp+p[0]/sizeof(fp)));
+ return prev_pc;
+ }
+ }
+ return 0;
+}
+#endif /* defined(__alpha__) && defined(__GNUC__) */
+
+void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
+{
+ uchar** fp;
+ uint frame_count = 0, sigreturn_frame_count;
+#if defined(__alpha__) && defined(__GNUC__)
+ uint32* pc;
+#endif
+ LINT_INIT(fp);
+
+
+#ifdef __i386__
+ __asm __volatile__ ("movl %%ebp,%0"
+ :"=r"(fp)
+ :"r"(fp));
+#endif
+#ifdef __x86_64__
+ __asm __volatile__ ("movq %%rbp,%0"
+ :"=r"(fp)
+ :"r"(fp));
+#endif
+#if defined(__alpha__) && defined(__GNUC__)
+ __asm __volatile__ ("mov $30,%0"
+ :"=r"(fp)
+ :"r"(fp));
+#endif
+ if (!fp)
+ {
+ fprintf(stderr, "frame pointer is NULL, did you compile with\n\
+-fomit-frame-pointer? Aborting backtrace!\n");
+ return;
+ }
+
+ if (!stack_bottom || (uchar*) stack_bottom > (uchar*) &fp)
+ {
+ ulong tmp= min(0x10000,thread_stack);
+ /* Assume that the stack starts at the previous even 65K */
+ stack_bottom= (uchar*) (((ulong) &fp + tmp) &
+ ~(ulong) 0xFFFF);
+ fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", fp);
+ }
+ if (fp > (uchar**) stack_bottom ||
+ fp < (uchar**) stack_bottom - thread_stack)
+ {
+ fprintf(stderr, "Bogus stack limit or frame pointer,\
+ fp=%p, stack_bottom=%p, thread_stack=%ld, aborting backtrace.\n",
+ fp, stack_bottom, thread_stack);
+ return;
+ }
+
+ fprintf(stderr, "Stack range sanity check OK, backtrace follows:\n");
+#if defined(__alpha__) && defined(__GNUC__)
+ fprintf(stderr, "Warning: Alpha stacks are difficult -\
+ will be taking some wild guesses, stack trace may be incorrect or \
+ terminate abruptly\n");
+ /* On Alpha, we need to get pc */
+ __asm __volatile__ ("bsr %0, do_next; do_next: "
+ :"=r"(pc)
+ :"r"(pc));
+#endif /* __alpha__ */
+
+ /* We are 1 frame above signal frame with NPTL and 2 frames above with LT */
+ sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1;
+
+ while (fp < (uchar**) stack_bottom)
+ {
+#if defined(__i386__) || defined(__x86_64__)
+ uchar** new_fp = (uchar**)*fp;
+ fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ?
+ *(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
+#endif /* defined(__386__) || defined(__x86_64__) */
+
+#if defined(__alpha__) && defined(__GNUC__)
+ uchar** new_fp = find_prev_fp(pc, fp);
+ if (frame_count == sigreturn_frame_count - 1)
+ {
+ new_fp += 90;
+ }
+
+ if (fp && pc)
+ {
+ pc = find_prev_pc(pc, fp);
+ if (pc)
+ fprintf(stderr, "%p\n", pc);
+ else
+ {
+ fprintf(stderr, "Not smart enough to deal with the rest\
+ of this stack\n");
+ goto end;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Not smart enough to deal with the rest of this stack\n");
+ goto end;
+ }
+#endif /* defined(__alpha__) && defined(__GNUC__) */
+ if (new_fp <= fp )
+ {
+ fprintf(stderr, "New value of fp=%p failed sanity check,\
+ terminating stack trace!\n", new_fp);
+ goto end;
+ }
+ fp = new_fp;
+ ++frame_count;
+ }
+
+ fprintf(stderr, "Stack trace seems successful - bottom reached\n");
+
+end:
+ fprintf(stderr,
+ "Please read http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
+ "and follow instructions on how to resolve the stack trace.\n"
+ "Resolved stack trace is much more helpful in diagnosing the\n"
+ "problem, so please do resolve it\n");
+}
+#endif /* TARGET_OS_LINUX */
+#endif /* HAVE_STACKTRACE */
+
+/* Produce a core for the thread */
+void my_write_core(int sig)
+{
+ signal(sig, SIG_DFL);
+#ifdef HAVE_gcov
+ /*
+ For GCOV build, crashing will prevent the writing of code coverage
+ information from this process, causing gcov output to be incomplete.
+ So we force the writing of coverage information here before terminating.
+ */
+ extern void __gcov_flush(void);
+ __gcov_flush();
+#endif
+ pthread_kill(pthread_self(), sig);
+#if defined(P_MYID) && !defined(SCO)
+ /* On Solaris, the above kill is not enough */
+ sigsend(P_PID,P_MYID,sig);
+#endif
+}
+
+#else /* __WIN__*/
+
+#include <dbghelp.h>
+
+/*
+ Stack tracing on Windows is implemented using Debug Helper library(dbghelp.dll)
+ We do not redistribute dbghelp and the one comes with older OS (up to Windows 2000)
+ is missing some important functions like functions StackWalk64 or MinidumpWriteDump.
+ Hence, we have to load functions at runtime using LoadLibrary/GetProcAddress.
+*/
+
+typedef DWORD (WINAPI *SymSetOptions_FctType)(DWORD dwOptions);
+typedef BOOL (WINAPI *SymGetModuleInfo64_FctType)
+ (HANDLE,DWORD64,PIMAGEHLP_MODULE64) ;
+typedef BOOL (WINAPI *SymGetSymFromAddr64_FctType)
+ (HANDLE,DWORD64,PDWORD64,PIMAGEHLP_SYMBOL64) ;
+typedef BOOL (WINAPI *SymGetLineFromAddr64_FctType)
+ (HANDLE,DWORD64,PDWORD,PIMAGEHLP_LINE64);
+typedef BOOL (WINAPI *SymInitialize_FctType)
+ (HANDLE,PSTR,BOOL);
+typedef BOOL (WINAPI *StackWalk64_FctType)
+ (DWORD,HANDLE,HANDLE,LPSTACKFRAME64,PVOID,PREAD_PROCESS_MEMORY_ROUTINE64,
+ PFUNCTION_TABLE_ACCESS_ROUTINE64,PGET_MODULE_BASE_ROUTINE64 ,
+ PTRANSLATE_ADDRESS_ROUTINE64);
+typedef BOOL (WINAPI *MiniDumpWriteDump_FctType)(
+ IN HANDLE hProcess,
+ IN DWORD ProcessId,
+ IN HANDLE hFile,
+ IN MINIDUMP_TYPE DumpType,
+ IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL
+ IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL
+ IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
+ );
+
+static SymSetOptions_FctType pSymSetOptions;
+static SymGetModuleInfo64_FctType pSymGetModuleInfo64;
+static SymGetSymFromAddr64_FctType pSymGetSymFromAddr64;
+static SymInitialize_FctType pSymInitialize;
+static StackWalk64_FctType pStackWalk64;
+static SymGetLineFromAddr64_FctType pSymGetLineFromAddr64;
+static MiniDumpWriteDump_FctType pMiniDumpWriteDump;
+
+static EXCEPTION_POINTERS *exception_ptrs;
+
+#define MODULE64_SIZE_WINXP 576
+#define STACKWALK_MAX_FRAMES 64
+
+void my_init_stacktrace()
+{
+}
+
+/*
+ Dynamically load dbghelp functions
+*/
+BOOL init_dbghelp_functions()
+{
+ static BOOL first_time= TRUE;
+ static BOOL rc;
+ HMODULE hDbghlp;
+
+ if(first_time)
+ {
+ first_time= FALSE;
+ hDbghlp= LoadLibrary("dbghelp");
+ if(!hDbghlp)
+ {
+ rc= FALSE;
+ return rc;
+ }
+ pSymSetOptions= (SymSetOptions_FctType)
+ GetProcAddress(hDbghlp,"SymSetOptions");
+ pSymInitialize= (SymInitialize_FctType)
+ GetProcAddress(hDbghlp,"SymInitialize");
+ pSymGetModuleInfo64= (SymGetModuleInfo64_FctType)
+ GetProcAddress(hDbghlp,"SymGetModuleInfo64");
+ pSymGetLineFromAddr64= (SymGetLineFromAddr64_FctType)
+ GetProcAddress(hDbghlp,"SymGetLineFromAddr64");
+ pSymGetSymFromAddr64=(SymGetSymFromAddr64_FctType)
+ GetProcAddress(hDbghlp,"SymGetSymFromAddr64");
+ pStackWalk64= (StackWalk64_FctType)
+ GetProcAddress(hDbghlp,"StackWalk64");
+ pMiniDumpWriteDump = (MiniDumpWriteDump_FctType)
+ GetProcAddress(hDbghlp,"MiniDumpWriteDump");
+
+ rc = (BOOL)(pSymSetOptions && pSymInitialize && pSymGetModuleInfo64
+ && pSymGetLineFromAddr64 && pSymGetSymFromAddr64 && pStackWalk64);
+ }
+ return rc;
+}
+
+void my_set_exception_pointers(EXCEPTION_POINTERS *ep)
+{
+ exception_ptrs = ep;
+}
+
+/* Platform SDK in VS2003 does not have definition for SYMOPT_NO_PROMPTS*/
+#ifndef SYMOPT_NO_PROMPTS
+#define SYMOPT_NO_PROMPTS 0
+#endif
+
+void my_print_stacktrace(uchar* unused1, ulong unused2)
+{
+ HANDLE hProcess= GetCurrentProcess();
+ HANDLE hThread= GetCurrentThread();
+ static IMAGEHLP_MODULE64 module= {sizeof(module)};
+ static IMAGEHLP_SYMBOL64_PACKAGE package;
+ DWORD64 addr;
+ DWORD machine;
+ int i;
+ CONTEXT context;
+ STACKFRAME64 frame={0};
+
+ if(!exception_ptrs || !init_dbghelp_functions())
+ return;
+
+ /* Copy context, as stackwalking on original will unwind the stack */
+ context = *(exception_ptrs->ContextRecord);
+ /*Initialize symbols.*/
+ pSymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG);
+ pSymInitialize(hProcess,NULL,TRUE);
+
+ /*Prepare stackframe for the first StackWalk64 call*/
+ frame.AddrFrame.Mode= frame.AddrPC.Mode= frame.AddrStack.Mode= AddrModeFlat;
+#if (defined _M_IX86)
+ machine= IMAGE_FILE_MACHINE_I386;
+ frame.AddrFrame.Offset= context.Ebp;
+ frame.AddrPC.Offset= context.Eip;
+ frame.AddrStack.Offset= context.Esp;
+#elif (defined _M_X64)
+ machine = IMAGE_FILE_MACHINE_AMD64;
+ frame.AddrFrame.Offset= context.Rbp;
+ frame.AddrPC.Offset= context.Rip;
+ frame.AddrStack.Offset= context.Rsp;
+#else
+ /*There is currently no need to support IA64*/
+#pragma error ("unsupported architecture")
+#endif
+
+ package.sym.SizeOfStruct= sizeof(package.sym);
+ package.sym.MaxNameLength= sizeof(package.name);
+
+ /*Walk the stack, output useful information*/
+ for(i= 0; i< STACKWALK_MAX_FRAMES;i++)
+ {
+ DWORD64 function_offset= 0;
+ DWORD line_offset= 0;
+ IMAGEHLP_LINE64 line= {sizeof(line)};
+ BOOL have_module= FALSE;
+ BOOL have_symbol= FALSE;
+ BOOL have_source= FALSE;
+
+ if(!pStackWalk64(machine, hProcess, hThread, &frame, &context, 0, 0, 0 ,0))
+ break;
+ addr= frame.AddrPC.Offset;
+
+ have_module= pSymGetModuleInfo64(hProcess,addr,&module);
+#ifdef _M_IX86
+ if(!have_module)
+ {
+ /*
+ ModuleInfo structure has been "compatibly" extended in releases after XP,
+ and its size was increased. To make XP dbghelp.dll function
+ happy, pretend passing the old structure.
+ */
+ module.SizeOfStruct= MODULE64_SIZE_WINXP;
+ have_module= pSymGetModuleInfo64(hProcess, addr, &module);
+ }
+#endif
+
+ have_symbol= pSymGetSymFromAddr64(hProcess, addr, &function_offset,
+ &(package.sym));
+ have_source= pSymGetLineFromAddr64(hProcess, addr, &line_offset, &line);
+
+ fprintf(stderr, "%p ", addr);
+ if(have_module)
+ {
+ char *base_image_name= strrchr(module.ImageName, '\\');
+ if(base_image_name)
+ base_image_name++;
+ else
+ base_image_name= module.ImageName;
+ fprintf(stderr, "%s!", base_image_name);
+ }
+ if(have_symbol)
+ fprintf(stderr, "%s()", package.sym.Name);
+ else if(have_module)
+ fprintf(stderr, "???");
+
+ if(have_source)
+ {
+ char *base_file_name= strrchr(line.FileName, '\\');
+ if(base_file_name)
+ base_file_name++;
+ else
+ base_file_name= line.FileName;
+ fprintf(stderr,"[%s:%u]", base_file_name, line.LineNumber);
+ }
+ fprintf(stderr, "\n");
+ }
+ fflush(stderr);
+}
+
+
+/*
+ Write dump. The dump is created in current directory,
+ file name is constructed from executable name plus
+ ".dmp" extension
+*/
+void my_write_core(int unused)
+{
+ char path[MAX_PATH];
+ char dump_fname[MAX_PATH]= "core.dmp";
+ MINIDUMP_EXCEPTION_INFORMATION info;
+ HANDLE hFile;
+
+ if(!exception_ptrs || !init_dbghelp_functions() || !pMiniDumpWriteDump)
+ return;
+
+ info.ExceptionPointers= exception_ptrs;
+ info.ClientPointers= FALSE;
+ info.ThreadId= GetCurrentThreadId();
+
+ if(GetModuleFileName(NULL, path, sizeof(path)))
+ {
+ _splitpath(path, NULL, NULL,dump_fname,NULL);
+ strncat(dump_fname, ".dmp", sizeof(dump_fname));
+ }
+
+ hFile= CreateFile(dump_fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ if(hFile)
+ {
+ /* Create minidump */
+ if(pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
+ hFile, MiniDumpNormal, &info, 0, 0))
+ {
+ fprintf(stderr, "Minidump written to %s\n",
+ _fullpath(path, dump_fname, sizeof(path)) ? path : dump_fname);
+ }
+ else
+ {
+ fprintf(stderr,"MiniDumpWriteDump() failed, last error %u\n",
+ GetLastError());
+ }
+ CloseHandle(hFile);
+ }
+ else
+ {
+ fprintf(stderr, "CreateFile(%s) failed, last error %u\n", dump_fname,
+ GetLastError());
+ }
+ fflush(stderr);
+}
+
+
+void my_safe_print_str(const char *name, const char *val, int len)
+{
+ fprintf(stderr,"%s at %p", name, val);
+ __try
+ {
+ fprintf(stderr,"=%.*s\n", len, val);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ fprintf(stderr,"is an invalid string pointer\n");
+ }
+}
+#endif /*__WIN__*/
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index d6877c8c998..97700f77e3f 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -355,10 +355,10 @@ void thr_lock_init(THR_LOCK *lock)
void thr_lock_delete(THR_LOCK *lock)
{
DBUG_ENTER("thr_lock_delete");
- VOID(pthread_mutex_destroy(&lock->mutex));
pthread_mutex_lock(&THR_LOCK_lock);
thr_lock_thread_list=list_delete(thr_lock_thread_list,&lock->list);
pthread_mutex_unlock(&THR_LOCK_lock);
+ pthread_mutex_destroy(&lock->mutex);
DBUG_VOID_RETURN;
}