summaryrefslogtreecommitdiff
path: root/plugin
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2020-07-10 22:48:35 +0400
committerAlexey Botchkov <holyfoot@askmonty.org>2020-07-10 22:48:35 +0400
commit873eb4a39737b36cea0db7fbe12d70919529060a (patch)
tree5e98ca0d7fb146f077bd70d4866bf436a30625cc /plugin
parent41221091f6541ea83eeec70732b92b94746a44e7 (diff)
downloadmariadb-git-873eb4a39737b36cea0db7fbe12d70919529060a.tar.gz
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.
Diffstat (limited to 'plugin')
-rw-r--r--plugin/auth_pam/auth_pam.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/plugin/auth_pam/auth_pam.c b/plugin/auth_pam/auth_pam.c
index 4275b7d6750..c1c05bba216 100644
--- a/plugin/auth_pam/auth_pam.c
+++ b/plugin/auth_pam/auth_pam.c
@@ -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;