Commit b38d3c3d authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-10907 MTR and server writes can interleave in the error log

Ensure atomic appends to the error log by using CreateFile with
FILE_APPEND_DATA flag to open error log file (both MTR and server)
parent d61e5260
......@@ -24,7 +24,7 @@ use File::Path;
use base qw(Exporter);
our @EXPORT= qw(IS_CYGWIN IS_WINDOWS IS_WIN32PERL
native_path posix_path mixed_path
check_socket_path_length process_alive);
check_socket_path_length process_alive open_for_append);
BEGIN {
if ($^O eq "cygwin") {
......@@ -161,4 +161,51 @@ sub process_alive {
}
use Symbol qw( gensym );
use if $^O eq 'MSWin32', 'Win32API::File', qw( CloseHandle CreateFile GetOsFHandle OsFHandleOpen OPEN_ALWAYS FILE_APPEND_DATA
FILE_SHARE_READ FILE_SHARE_WRITE FILE_SHARE_DELETE );
use if $^O eq 'MSWin32', 'Win32::API';
use constant WIN32API_FILE_NULL => [];
# Open a file for append
# On Windows we use CreateFile with FILE_APPEND_DATA
# to insure that writes are atomic, not interleaved
# with writes by another processes.
sub open_for_append
{
my ($file) = @_;
my $fh = gensym();
if (IS_WIN32PERL)
{
my $handle;
if (!($handle = CreateFile(
$file,
FILE_APPEND_DATA(),
FILE_SHARE_READ()|FILE_SHARE_WRITE()|FILE_SHARE_DELETE(),
WIN32API_FILE_NULL,
OPEN_ALWAYS(),# Create if doesn't exist.
0,
WIN32API_FILE_NULL,
)))
{
return undef;
}
if (!OsFHandleOpen($fh, $handle, 'wat'))
{
CloseHandle($handle);
return undef;
}
return $fh;
}
open($fh,">>",$file) or return undef;
return $fh;
}
1;
......@@ -21,6 +21,7 @@
use strict;
use Carp;
use My::Platform;
sub mtr_fromfile ($);
sub mtr_tofile ($@);
......@@ -45,10 +46,10 @@ sub mtr_fromfile ($) {
sub mtr_tofile ($@) {
my $file= shift;
open(FILE,">>",$file) or mtr_error("can't open file \"$file\": $!");
print FILE join("", @_);
close FILE;
my $fh= open_for_append $file;
mtr_error("can't open file \"$file\": $!") unless defined($fh);
print $fh join("", @_);
close $fh;
}
......
......@@ -102,6 +102,7 @@ static FILE *my_win_freopen(const char *path, const char *mode, FILE *stream)
HANDLE osfh;
DBUG_ASSERT(path && stream);
DBUG_ASSERT(strchr(mode, 'a')); /* We use FILE_APPEND_DATA below */
/* Services don't have stdout/stderr on Windows, so _fileno returns -1. */
if (fd < 0)
......@@ -112,15 +113,14 @@ static FILE *my_win_freopen(const char *path, const char *mode, FILE *stream)
fd= _fileno(stream);
}
if ((osfh= CreateFile(path, GENERIC_READ | GENERIC_WRITE,
if ((osfh= CreateFile(path, GENERIC_READ | FILE_APPEND_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE |
FILE_SHARE_DELETE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
return NULL;
if ((handle_fd= _open_osfhandle((intptr_t)osfh,
_O_APPEND | _O_TEXT)) == -1)
if ((handle_fd= _open_osfhandle((intptr_t)osfh, _O_TEXT)) == -1)
{
CloseHandle(osfh);
return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment