mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Merge MySQL->MariaDB
* Finished Monty and Jani's merge * Some InnoDB tests still fail (because it's old xtradb code run against newer testsuite). They are expected to go after mergning with the latest xtradb.
This commit is contained in:
@ -22,6 +22,33 @@ use My::Platform;
|
||||
|
||||
use File::Temp qw/ tempfile tempdir /;
|
||||
|
||||
my $hint_mysqld; # Last resort guess for executable path
|
||||
|
||||
# If path in core file is 79 chars we assume it's been truncated
|
||||
# Looks like we can still find the full path using 'strings'
|
||||
# If that doesn't work, use the hint (mysqld path) as last resort.
|
||||
|
||||
sub _verify_binpath {
|
||||
my ($binary, $core_name)= @_;
|
||||
my $binpath;
|
||||
|
||||
if (length $binary != 79) {
|
||||
$binpath= $binary;
|
||||
print "Core generated by '$binpath'\n";
|
||||
} else {
|
||||
# Last occurrence of path ending in /mysql*, cut from first /
|
||||
if (`strings '$core_name' | grep "/mysql[^/. ]*\$" | tail -1` =~ /(\/.*)/) {
|
||||
$binpath= $1;
|
||||
print "Guessing that core was generated by '$binpath'\n";
|
||||
} else {
|
||||
return unless $hint_mysqld;
|
||||
$binpath= $hint_mysqld;
|
||||
print "Wild guess that core was generated by '$binpath'\n";
|
||||
}
|
||||
}
|
||||
return $binpath;
|
||||
}
|
||||
|
||||
sub _gdb {
|
||||
my ($core_name)= @_;
|
||||
|
||||
@ -33,7 +60,8 @@ sub _gdb {
|
||||
`gdb -c '$core_name' --batch 2>&1` =~
|
||||
/Core was generated by `([^\s\'\`]+)/;
|
||||
my $binary= $1 or return;
|
||||
print "Core generated by '$binary'\n";
|
||||
|
||||
$binary= _verify_binpath ($binary, $core_name) or return;
|
||||
|
||||
# Create tempfile containing gdb commands
|
||||
my ($tmp, $tmp_name) = tempfile();
|
||||
@ -73,7 +101,8 @@ sub _dbx {
|
||||
`echo | dbx - '$core_name' 2>&1` =~
|
||||
/Corefile specified executable: "([^"]+)"/;
|
||||
my $binary= $1 or return;
|
||||
print "Core generated by '$binary'\n";
|
||||
|
||||
$binary= _verify_binpath ($binary, $core_name) or return;
|
||||
|
||||
# Find all threads
|
||||
my @thr_ids = `echo threads | dbx '$binary' '$core_name' 2>&1` =~ /t@\d+/g;
|
||||
@ -203,7 +232,7 @@ sub _cdb {
|
||||
|
||||
my $cdb_cmd = "!sym prompts off; !analyze -v; .ecxr; !for_each_frame dv /t;!uniqstack -p;q";
|
||||
my $cdb_output=
|
||||
`cdb -z $core_name -i "$image_path" -y "$symbol_path" -t 0 -lines -c "$cdb_cmd" 2>&1`;
|
||||
`cdb -c "$cdb_cmd" -z $core_name -i "$image_path" -y "$symbol_path" -t 0 -lines 2>&1`;
|
||||
return if $? >> 8;
|
||||
return unless $cdb_output;
|
||||
|
||||
@ -225,7 +254,8 @@ EOF
|
||||
|
||||
|
||||
sub show {
|
||||
my ($class, $core_name)= @_;
|
||||
my ($class, $core_name, $exe_mysqld)= @_;
|
||||
$hint_mysqld= $exe_mysqld;
|
||||
|
||||
# On Windows, rely on cdb to be there...
|
||||
if (IS_WINDOWS)
|
||||
|
@ -164,6 +164,9 @@ sub copytree {
|
||||
copytree("$from_dir/$_", "$to_dir/$_");
|
||||
next;
|
||||
}
|
||||
|
||||
# Only copy plain files
|
||||
next unless -f "$from_dir/$_";
|
||||
copy("$from_dir/$_", "$to_dir/$_");
|
||||
}
|
||||
closedir(DIR);
|
||||
|
@ -536,7 +536,37 @@ sub wait_any {
|
||||
return $proc;
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Wait for all processes to exit
|
||||
#
|
||||
sub wait_all {
|
||||
while(keys %running)
|
||||
{
|
||||
wait_any();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Check if any process has exited, but don't wait.
|
||||
#
|
||||
# Returns a reference to the SafeProcess that
|
||||
# exited or undefined
|
||||
#
|
||||
sub check_any {
|
||||
for my $proc (values %running){
|
||||
if ( $proc->is_child($$) ) {
|
||||
if (not $proc->wait_one(0)) {
|
||||
_verbose ("Found exited $proc");
|
||||
return $proc;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
# Overload string operator
|
||||
# and fallback to default functions if no
|
||||
# overloaded function is found
|
||||
|
@ -83,6 +83,13 @@ sub exit_status {
|
||||
};
|
||||
}
|
||||
|
||||
# threads.pm may not exist everywhere, so use only on Windows.
|
||||
|
||||
use if $^O eq "MSWin32", "threads";
|
||||
use if $^O eq "MSWin32", "threads::shared";
|
||||
|
||||
my $win32_spawn_lock :shared;
|
||||
|
||||
|
||||
#
|
||||
# Create a new process
|
||||
@ -104,6 +111,8 @@ sub create_process {
|
||||
|
||||
if ($^O eq "MSWin32"){
|
||||
|
||||
lock($win32_spawn_lock);
|
||||
|
||||
#printf STDERR "stdin %d, stdout %d, stderr %d\n",
|
||||
# fileno STDIN, fileno STDOUT, fileno STDERR;
|
||||
|
||||
|
@ -89,7 +89,7 @@ static void die(const char* fmt, ...)
|
||||
}
|
||||
|
||||
|
||||
static void kill_child (void)
|
||||
static void kill_child(void)
|
||||
{
|
||||
int status= 0;
|
||||
|
||||
@ -119,7 +119,7 @@ static void kill_child (void)
|
||||
}
|
||||
|
||||
|
||||
static void handle_abort (int sig)
|
||||
extern "C" void handle_abort(int sig)
|
||||
{
|
||||
message("Got signal %d, child_pid: %d, sending ABRT", sig, child_pid);
|
||||
|
||||
@ -128,8 +128,8 @@ static void handle_abort (int sig)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void handle_signal (int sig)
|
||||
|
||||
extern "C" void handle_signal(int sig)
|
||||
{
|
||||
message("Got signal %d, child_pid: %d", sig, child_pid);
|
||||
terminated= 1;
|
||||
@ -152,7 +152,7 @@ int main(int argc, char* const argv[] )
|
||||
pid_t own_pid= getpid();
|
||||
pid_t parent_pid= getppid();
|
||||
bool nocore = false;
|
||||
|
||||
|
||||
/* Install signal handlers */
|
||||
signal(SIGTERM, handle_signal);
|
||||
signal(SIGINT, handle_signal);
|
||||
@ -232,10 +232,11 @@ int main(int argc, char* const argv[] )
|
||||
message("setrlimit failed, errno=%d", errno);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Signal that child is ready
|
||||
buf= 37;
|
||||
write(pfd[1], &buf, 1);
|
||||
if ((write(pfd[1], &buf, 1)) < 1)
|
||||
die("Failed to signal that child is ready");
|
||||
// Close write end
|
||||
close(pfd[1]);
|
||||
|
||||
@ -246,8 +247,10 @@ int main(int argc, char* const argv[] )
|
||||
close(pfd[1]); // Close unused write end
|
||||
|
||||
// Wait for child to signal it's ready
|
||||
read(pfd[0], &buf, 1);
|
||||
if(buf != 37)
|
||||
if ((read(pfd[0], &buf, 1)) < 1)
|
||||
die("Failed to read signal from child");
|
||||
|
||||
if (buf != 37)
|
||||
die("Didn't get 37 from pipe");
|
||||
close(pfd[0]); // Close read end
|
||||
|
||||
@ -272,7 +275,7 @@ int main(int argc, char* const argv[] )
|
||||
if (WIFEXITED(status))
|
||||
{
|
||||
// Process has exited, collect return status
|
||||
int ret_code= WEXITSTATUS(status);
|
||||
ret_code= WEXITSTATUS(status);
|
||||
message("Child exit: %d", ret_code);
|
||||
// Exit with exit status of the child
|
||||
exit(ret_code);
|
||||
@ -287,6 +290,6 @@ int main(int argc, char* const argv[] )
|
||||
}
|
||||
kill_child();
|
||||
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -259,22 +259,37 @@ int main(int argc, const char** argv )
|
||||
the JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag, making sure it will be
|
||||
terminated when the last handle to it is closed(which is owned by
|
||||
this process).
|
||||
|
||||
If breakaway from job fails on some reason, fallback is to create a
|
||||
new process group. Process groups also allow to kill process and its
|
||||
descedants, subject to some restrictions (processes have to run within
|
||||
the same console,and must not ignore CTRL_BREAK)
|
||||
*/
|
||||
if (CreateProcess(NULL, (LPSTR)child_args,
|
||||
DWORD create_flags[]= {CREATE_BREAKAWAY_FROM_JOB, CREATE_NEW_PROCESS_GROUP, 0};
|
||||
BOOL process_created= FALSE;
|
||||
BOOL jobobject_assigned= FALSE;
|
||||
|
||||
for (int i=0; i < sizeof(create_flags)/sizeof(create_flags[0]); i++)
|
||||
{
|
||||
process_created= CreateProcess(NULL, (LPSTR)child_args,
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE, /* inherit handles */
|
||||
CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB,
|
||||
CREATE_SUSPENDED | create_flags[i],
|
||||
NULL,
|
||||
NULL,
|
||||
&si,
|
||||
&process_info) == 0)
|
||||
die("CreateProcess failed");
|
||||
&process_info);
|
||||
if (process_created)
|
||||
{
|
||||
jobobject_assigned= AssignProcessToJobObject(job_handle, process_info.hProcess);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (AssignProcessToJobObject(job_handle, process_info.hProcess) == 0)
|
||||
if (!process_created)
|
||||
{
|
||||
TerminateProcess(process_info.hProcess, 200);
|
||||
die("AssignProcessToJobObject failed");
|
||||
die("CreateProcess failed");
|
||||
}
|
||||
ResumeThread(process_info.hThread);
|
||||
CloseHandle(process_info.hThread);
|
||||
@ -312,6 +327,13 @@ int main(int argc, const char** argv )
|
||||
message("TerminateJobObject failed");
|
||||
CloseHandle(job_handle);
|
||||
message("Job terminated and closed");
|
||||
|
||||
if (!jobobject_assigned)
|
||||
{
|
||||
GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, process_info.dwProcessId);
|
||||
TerminateProcess(process_info.hProcess, 202);
|
||||
}
|
||||
|
||||
if (wait_res != WAIT_OBJECT_0 + CHILD)
|
||||
{
|
||||
/* The child has not yet returned, wait for it */
|
||||
|
Reference in New Issue
Block a user