Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
cf9053f1
Commit
cf9053f1
authored
Jan 18, 2008
by
msvensson@shellback.(none)
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add C version of safe_process
parent
481e8fec
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
318 additions
and
14 deletions
+318
-14
.bzrignore
.bzrignore
+1
-0
configure.in
configure.in
+1
-1
mysql-test/Makefile.am
mysql-test/Makefile.am
+2
-0
mysql-test/lib/My/SafeProcess.pm
mysql-test/lib/My/SafeProcess.pm
+24
-11
mysql-test/lib/My/SafeProcess/Makefile.am
mysql-test/lib/My/SafeProcess/Makefile.am
+21
-0
mysql-test/lib/My/SafeProcess/safe_process.cc
mysql-test/lib/My/SafeProcess/safe_process.cc
+267
-0
mysql-test/lib/t/SafeProcessStress.pl
mysql-test/lib/t/SafeProcessStress.pl
+2
-2
No files found.
.bzrignore
View file @
cf9053f1
...
...
@@ -3005,3 +3005,4 @@ win/vs71cache.txt
win/vs8cache.txt
zlib/*.ds?
zlib/*.vcproj
mysql-test/lib/My/SafeProcess/my_safe_process
configure.in
View file @
cf9053f1
...
...
@@ -2680,7 +2680,7 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
server-tools/Makefile server-tools/instance-manager/Makefile dnl
cmd-line-utils/Makefile cmd-line-utils/libedit/Makefile dnl
libmysqld/Makefile libmysqld/examples/Makefile dnl
mysql-test/Makefile dnl
mysql-test/Makefile
mysql-test/lib/My/SafeProcess/Makefile
dnl
netware/Makefile sql-bench/Makefile dnl
include/mysql_version.h plugin/Makefile win/Makefile)
...
...
mysql-test/Makefile.am
View file @
cf9053f1
...
...
@@ -29,6 +29,8 @@ EXTRA_DIST = README \
test_SCRIPTS
=
mtr mysql-test-run
CLEANFILES
=
$(test_SCRIPTS)
SUBDIRS
=
lib/My/SafeProcess
# Install all files and files in directories listed in EXTRA_DIST
install-data-local
:
...
...
mysql-test/lib/My/SafeProcess.pm
View file @
cf9053f1
...
...
@@ -90,22 +90,35 @@ my @safe_process_cmd;
my
$safe_kill
;
if
(
IS_WIN32PERL
or
IS_CYGWIN
){
# Use my_safe_process.exe
my
$exe
=
my_find_bin
("
.
",
"
lib/My/SafeProcess
",
"
my_safe_process.exe
");
die
"
Could not find my_safe_process.exe
"
unless
$exe
;
my
$exe
=
my_find_bin
("
.
",
["
lib/My/SafeProcess
",
"
My/SafeProcess
"],
"
my_safe_process
");
die
"
Could not find my_safe_process
"
unless
$exe
;
push
(
@safe_process_cmd
,
$exe
);
# Use my_safe_kill.exe
my
$safe_kill
=
my_find_bin
("
.
",
"
lib/My/SafeProcess
",
"
my_safe_kill
");
die
"
Could not find my_safe_kill
.exe
"
unless
$safe_kill
;
die
"
Could not find my_safe_kill
"
unless
$safe_kill
;
}
else
{
# Use safe_process.pl
my
$script
=
"
lib/My/SafeProcess/safe_process.pl
";
$script
=
"
../
$script
"
unless
-
f
$script
;
die
"
Could not find safe_process.pl
"
unless
-
f
$script
;
# Call $script with Perl interpreter
push
(
@safe_process_cmd
,
$^X
,
$script
);
else
{
my
$use_safe_process_binary
=
1
;
if
(
$use_safe_process_binary
)
{
# Use my_safe_process
my
$exe
=
my_find_bin
("
.
",
["
lib/My/SafeProcess
",
"
My/SafeProcess
"],
"
my_safe_process
");
die
"
Could not find my_safe_process
"
unless
$exe
;
push
(
@safe_process_cmd
,
$exe
);
}
else
{
# Use safe_process.pl
my
$script
=
"
lib/My/SafeProcess/safe_process.pl
";
$script
=
"
../
$script
"
unless
-
f
$script
;
die
"
Could not find safe_process.pl
"
unless
-
f
$script
;
# Call $script with Perl interpreter
push
(
@safe_process_cmd
,
$^X
,
$script
);
}
}
...
...
mysql-test/lib/My/SafeProcess/Makefile.am
0 → 100644
View file @
cf9053f1
# Copyright (C) 2000-2006 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
bin_PROGRAMS
=
my_safe_process
my_safe_process_SOURCES
=
safe_process.cc
# Don't update the files from bitkeeper
%
::
SCCS/s.%
mysql-test/lib/My/SafeProcess/safe_process.cc
0 → 100644
View file @
cf9053f1
/* Copyright (C) 2008 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 */
/*
Utility program that encapsulates process creation, monitoring
and bulletproof process cleanup
Usage:
safe_process [options to safe_process] -- progname arg1 ... argn
To safeguard mysqld you would invoke safe_process with a few options
for safe_process itself followed by a double dash to indicate start
of the command line for the program you really want to start
$> safe_process --output=output.log -- mysqld --datadir=var/data1 ...
This would redirect output to output.log and then start mysqld,
once it has done that it will continue to monitor the child as well
as the parent.
The safe_process then checks the follwing things:
1. Child exits, propagate the childs return code to the parent
by exiting with the same return code as the child.
2. Parent dies, immediately kill the child and exit, thus the
parent does not need to properly cleanup any child, it is handled
automatically.
3. Signal's recieced by the process will trigger same action as 2)
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
int
verbose
=
0
;
int
terminated
=
0
;
pid_t
child_pid
=
-
1
;
char
safe_process_name
[
32
]
=
{
0
};
static
void
message
(
const
char
*
fmt
,
...)
{
if
(
!
verbose
)
return
;
va_list
args
;
fprintf
(
stderr
,
"%s: "
,
safe_process_name
);
va_start
(
args
,
fmt
);
vfprintf
(
stderr
,
fmt
,
args
);
fprintf
(
stderr
,
"
\n
"
);
va_end
(
args
);
fflush
(
stderr
);
}
static
void
die
(
const
char
*
fmt
,
...)
{
va_list
args
;
fprintf
(
stderr
,
"%s: FATAL ERROR, "
,
safe_process_name
);
va_start
(
args
,
fmt
);
vfprintf
(
stderr
,
fmt
,
args
);
fprintf
(
stderr
,
"
\n
"
);
va_end
(
args
);
if
(
int
last_err
=
errno
)
fprintf
(
stderr
,
"error: %d, %s
\n
"
,
last_err
,
strerror
(
last_err
));
exit
(
1
);
}
static
void
kill_child
(
void
)
{
int
exit_code
=
1
;
int
status
=
0
;
message
(
"Killing child: %d"
,
child_pid
);
// Terminate whole process group
kill
(
-
child_pid
,
SIGKILL
);
pid_t
ret_pid
=
waitpid
(
child_pid
,
&
status
,
0
);
if
(
ret_pid
==
child_pid
)
{
if
(
WIFEXITED
(
status
))
{
// Process has exited, collect return status
exit_code
=
WEXITSTATUS
(
status
);
message
(
"Child exit: %d"
,
exit_code
);
// Exit with exit status of the child
exit
(
exit_code
);
}
if
(
WIFSIGNALED
(
status
))
message
(
"Child killed by signal: %d"
,
WTERMSIG
(
status
));
exit
(
exit_code
);
}
exit
(
exit_code
);
}
static
void
handle_signal
(
int
sig
)
{
message
(
"Got signal %d, child_pid: %d"
,
sig
,
child_pid
);
terminated
=
1
;
// Ignore further signals
signal
(
SIGTERM
,
SIG_IGN
);
signal
(
SIGINT
,
SIG_IGN
);
signal
(
SIGCHLD
,
SIG_IGN
);
if
(
child_pid
>
0
)
kill_child
();
// Continune execution, allow the child to be started and
// finally terminated by monitor loop
}
int
main
(
int
argc
,
char
*
const
argv
[]
)
{
char
*
const
*
child_argv
=
0
;
pid_t
own_pid
=
getpid
();
pid_t
parent_pid
=
getppid
();
/* Install signal handlers */
signal
(
SIGTERM
,
handle_signal
);
signal
(
SIGINT
,
handle_signal
);
signal
(
SIGCHLD
,
handle_signal
);
sprintf
(
safe_process_name
,
"safe_process[%d]"
,
own_pid
);
message
(
"Started"
);
/* Parse arguments */
for
(
int
i
=
1
;
i
<
argc
;
i
++
)
{
const
char
*
arg
=
argv
[
i
];
if
(
strcmp
(
arg
,
"--"
)
==
0
&&
strlen
(
arg
)
==
2
)
{
/* Got the "--" delimiter */
if
(
i
>=
argc
)
die
(
"No real args -> nothing to do"
);
child_argv
=
&
argv
[
i
+
1
];
break
;
}
else
{
if
(
strcmp
(
arg
,
"--verbose"
)
==
0
)
verbose
++
;
else
if
(
strncmp
(
arg
,
"--parent-pid"
,
10
)
==
0
)
{
/* Override parent_pid with a value provided by user */
const
char
*
start
;
if
((
start
=
strstr
(
arg
,
"="
))
==
NULL
)
die
(
"Could not find start of option value in '%s'"
,
arg
);
start
++
;
/* Step past = */
if
((
parent_pid
=
atoi
(
start
))
==
0
)
die
(
"Invalid value '%s' passed to --parent-id"
,
start
);
}
else
die
(
"Unknown option: %s"
,
arg
);
}
}
if
(
!
child_argv
||
*
child_argv
==
0
)
die
(
"nothing to do"
);
message
(
"parent_pid: %d"
,
parent_pid
);
if
(
parent_pid
==
own_pid
)
die
(
"parent_pid is equal to own pid!"
);
char
buf
;
int
pfd
[
2
];
if
(
pipe
(
pfd
)
==
-
1
)
die
(
"Failed to create pipe"
);
/* Create the child process */
while
((
child_pid
=
fork
())
==
-
1
)
{
message
(
"fork failed"
);
sleep
(
1
);
}
if
(
child_pid
==
0
)
{
close
(
pfd
[
0
]);
// Close unused read end
// Use default signal handlers in child
signal
(
SIGTERM
,
SIG_DFL
);
signal
(
SIGINT
,
SIG_DFL
);
signal
(
SIGCHLD
,
SIG_DFL
);
// Make this process it's own process group to be able to kill
// it and any childs(that hasn't changed group themself)
setpgid
(
0
,
0
);
// Signal that child is ready
buf
=
37
;
write
(
pfd
[
1
],
&
buf
,
1
);
// Close write end
close
(
pfd
[
1
]);
if
(
execvp
(
child_argv
[
0
],
child_argv
)
<
0
)
die
(
"Failed to exec child"
);
}
close
(
pfd
[
1
]);
// Close unused write end
// Wait for child to signal it's ready
read
(
pfd
[
0
],
&
buf
,
1
);
if
(
buf
!=
37
)
die
(
"Didn't get 37 from pipe"
);
close
(
pfd
[
0
]);
// Close read end
/* Monitor loop */
message
(
"Started child %d, terminated: %d"
,
child_pid
,
terminated
);
while
(
!
terminated
)
{
// Check if parent is still alive
if
(
kill
(
parent_pid
,
0
)
!=
0
){
message
(
"Parent is not alive anymore"
);
break
;
}
// Check if child has exited, normally this wil be
// detected immediately with SIGCHLD handler
int
status
=
0
;
pid_t
ret_pid
=
waitpid
(
child_pid
,
&
status
,
WNOHANG
);
if
(
ret_pid
==
child_pid
)
{
int
ret_code
=
2
;
if
(
WIFEXITED
(
status
))
{
// Process has exited, collect return status
int
ret_code
=
WEXITSTATUS
(
status
);
message
(
"Child exit: %d"
,
ret_code
);
// Exit with exit status of the child
exit
(
ret_code
);
}
if
(
WIFSIGNALED
(
status
))
message
(
"Child killed by signal: %d"
,
WTERMSIG
(
status
));
exit
(
ret_code
);
}
sleep
(
1
);
}
kill_child
();
exit
(
1
);
}
mysql-test/lib/t/SafeProcessStress.pl
View file @
cf9053f1
...
...
@@ -11,7 +11,7 @@ use My::SafeProcess;
my
$perl_path
=
$^X
;
my
$verbose
=
0
;
my
$loops
=
100
0
;
my
$loops
=
100
;
print
"
kill one and wait for one
\n
";
for
(
1
...
$loops
){
...
...
@@ -33,7 +33,7 @@ for (1...$loops){
foreach
my
$proc
(
@procs
)
{
$proc
->
kill
();
# dummyd will always be kiled and thus
# dummyd will always be kil
l
ed and thus
# exit_status should have been set to 1
die
"
oops, exit_status:
",
$proc
->
exit_status
()
unless
$proc
->
exit_status
()
==
1
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment