MDEV-21385 PAM v2 plugin produces lots of zombie processes.

The auth_pam_tool that is executed from pam_auth() can be still
not finished by the time we do the waitpid() there.
As we use WNOHANG option for the waitpid(), it didn't wait and
left the zombie process. So let's do the loop of waitpid() with the
limited number of sleeps.
This commit is contained in:
Alexey Botchkov 2020-07-10 22:48:35 +04:00
commit 873eb4a397

View file

@ -36,12 +36,20 @@ static char *opt_plugin_dir; /* To be dynamically linked. */
static const char *tool_name= "auth_pam_tool_dir/auth_pam_tool";
static const int tool_name_len= 31;
/*
sleep_limit is now 5 meaning up to 1 second sleep.
each step means 10 times longer sleep, so 6 would mean 10 seconds.
*/
static const unsigned int sleep_limit= 5;
static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
{
int p_to_c[2], c_to_p[2]; /* Parent-to-child and child-to-parent pipes. */
pid_t proc_id;
int result= CR_ERROR, pkt_len= 0;
unsigned char field, *pkt;
unsigned int n_sleep= 0;
useconds_t sleep_time= 100;
PAM_DEBUG((stderr, "PAM: opening pipes.\n"));
if (pipe(p_to_c) < 0 || pipe(c_to_p) < 0)
@ -190,7 +198,24 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
error_ret:
close(p_to_c[1]);
close(c_to_p[0]);
waitpid(proc_id, NULL, WNOHANG);
while (waitpid(proc_id, NULL, WNOHANG) != (int) proc_id)
{
if (n_sleep++ == sleep_limit)
{
/*
The auth_pam_tool application doesn't terminate.
Means something wrong happened there like pam_xxx.so hanged.
*/
kill(proc_id, SIGKILL);
sleep_time= 1000000; /* 1 second wait should be enough. */
PAM_DEBUG((stderr, "PAM: auth_pam_tool doesn't terminate,"
" have to kill it.\n"));
}
else if (n_sleep > sleep_limit)
break;
usleep(sleep_time);
sleep_time*= 10;
}
PAM_DEBUG((stderr, "PAM: auth result %d.\n", result));
return result;