summaryrefslogtreecommitdiff
path: root/sql/log.cc
diff options
context:
space:
mode:
authorDavi Arnaut <davi.arnaut@oracle.com>2011-01-07 16:33:36 -0200
committerDavi Arnaut <davi.arnaut@oracle.com>2011-01-07 16:33:36 -0200
commit998065c3a6f3d65e88c3926b31088a245f77406d (patch)
treeba6cafa745b463dda5c02cec1d1fdeacc9953310 /sql/log.cc
parentd2b0c83646292a85f4600ef6316167cd7571d471 (diff)
downloadmariadb-git-998065c3a6f3d65e88c3926b31088a245f77406d.tar.gz
Bug#51023: Mysql server crashes on SIGHUP and destroys InnoDB files
From a user perspective, the problem is that a FLUSH LOGS or SIGHUP signal could end up associating the stdout and stderr to random files. In the case of this bug report, the streams would end up associated to InnoDB ibd files. The freopen(3) function is not thread-safe on FreeBSD. What this means is that if another thread calls open(2) during freopen() is executing that another thread's fd returned by open(2) may get re-associated with the file being passed to freopen(3). See FreeBSD PR number 79887 for reference: http://www.freebsd.org/cgi/query-pr.cgi?pr=79887 This problem is worked around by substituting a internal hook within the FILE structure. This avoids the loss of atomicity by not having the original fd closed before its duplicated. Patch based on the original work by Vasil Dimov. include/my_sys.h: Export my_freopen. mysys/my_fopen.c: Add a my_freopen abstraction to workaround bugs in specific OSes. Add a prototype for getosreldate() as older FreeBSD versions did not define one. sql/log.cc: Move freopen abstraction code over to mysys. The streams are now only reopened for writing.
Diffstat (limited to 'sql/log.cc')
-rw-r--r--sql/log.cc74
1 files changed, 10 insertions, 64 deletions
diff --git a/sql/log.cc b/sql/log.cc
index f3d3420194c..23182fa1902 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -5171,80 +5171,26 @@ void sql_perror(const char *message)
}
-#ifdef __WIN__
+/*
+ Change the file associated with two output streams. Used to
+ redirect stdout and stderr to a file. The streams are reopened
+ only for appending (writing at end of file).
+*/
extern "C" my_bool reopen_fstreams(const char *filename,
FILE *outstream, FILE *errstream)
{
- int handle_fd;
- int err_fd, out_fd;
- HANDLE osfh;
-
- DBUG_ASSERT(filename && errstream);
-
- // Services don't have stdout/stderr on Windows, so _fileno returns -1.
- err_fd= _fileno(errstream);
- if (err_fd < 0)
- {
- if (!freopen(filename, "a+", errstream))
- return TRUE;
-
- setbuf(errstream, NULL);
- err_fd= _fileno(errstream);
- }
-
- if (outstream)
- {
- out_fd= _fileno(outstream);
- if (out_fd < 0)
- {
- if (!freopen(filename, "a+", outstream))
- return TRUE;
- out_fd= _fileno(outstream);
- }
- }
-
- if ((osfh= CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE |
- FILE_SHARE_DELETE, NULL,
- OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
- NULL)) == INVALID_HANDLE_VALUE)
+ if (outstream && !my_freopen(filename, "a", outstream))
return TRUE;
- if ((handle_fd= _open_osfhandle((intptr_t)osfh,
- _O_APPEND | _O_TEXT)) == -1)
- {
- CloseHandle(osfh);
+ if (errstream && !my_freopen(filename, "a", errstream))
return TRUE;
- }
- if (_dup2(handle_fd, err_fd) < 0)
- {
- CloseHandle(osfh);
- return TRUE;
- }
-
- if (outstream && _dup2(handle_fd, out_fd) < 0)
- {
- CloseHandle(osfh);
- return TRUE;
- }
-
- _close(handle_fd);
- return FALSE;
-}
-#else
-extern "C" my_bool reopen_fstreams(const char *filename,
- FILE *outstream, FILE *errstream)
-{
- if (outstream && !freopen(filename, "a+", outstream))
- return TRUE;
-
- if (errstream && !freopen(filename, "a+", errstream))
- return TRUE;
+ /* The error stream must be unbuffered. */
+ if (errstream)
+ setbuf(errstream, NULL);
return FALSE;
}
-#endif
/*