From ac45ddd2d7b8415566dabc0ca1db3683dfa15ec9 Mon Sep 17 00:00:00 2001 From: Dirkjan Bussink Date: Tue, 5 Mar 2024 20:45:39 +0100 Subject: [PATCH] mysqlctl: Improve handling of the lock file This handles the case where mysqlctld might get assigned the same pid and improves the logging for when this case happens. Signed-off-by: Dirkjan Bussink --- go/vt/mysqlctl/mysqld.go | 12 +++++++++++- go/vt/mysqlctl/mysqld_test.go | 8 +++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/go/vt/mysqlctl/mysqld.go b/go/vt/mysqlctl/mysqld.go index 5b2d4fc19b7..63971339f13 100644 --- a/go/vt/mysqlctl/mysqld.go +++ b/go/vt/mysqlctl/mysqld.go @@ -460,6 +460,10 @@ func cleanupLockfile(socket string, ts string) error { log.Errorf("%v: error parsing pid from lock file: %v", ts, err) return err } + if os.Getpid() == p { + log.Infof("%v: lock file at %s is ours, removing it", ts, lockPath) + return os.Remove(lockPath) + } proc, err := os.FindProcess(p) if err != nil { log.Errorf("%v: error finding process: %v", ts, err) @@ -469,7 +473,13 @@ func cleanupLockfile(socket string, ts string) error { if err == nil { // If the process still exists, it's not safe to // remove the lock file, so we have to keep it around. - log.Errorf("%v: not removing socket lock file: %v with pid %v", ts, lockPath, p) + cmdline, err := os.ReadFile(fmt.Sprintf("/proc/%d/cmdline", p)) + if err == nil { + name := string(bytes.ReplaceAll(cmdline, []byte{0}, []byte(" "))) + log.Errorf("%v: not removing socket lock file: %v with pid %v for %q", ts, lockPath, p, name) + } else { + log.Errorf("%v: not removing socket lock file: %v with pid %v (failed to read process name: %v)", ts, lockPath, p, err) + } return fmt.Errorf("process %v is still running", p) } if !errors.Is(err, os.ErrProcessDone) { diff --git a/go/vt/mysqlctl/mysqld_test.go b/go/vt/mysqlctl/mysqld_test.go index 0caba8c904d..b1e5e9a2916 100644 --- a/go/vt/mysqlctl/mysqld_test.go +++ b/go/vt/mysqlctl/mysqld_test.go @@ -193,8 +193,14 @@ func TestCleanupLockfile(t *testing.T) { assert.NoError(t, cleanupLockfile("mysql.sock", ts)) assert.NoFileExists(t, "mysql.sock.lock") - // If the lockfile exists, and the process is found, we don't clean it up. + // If the lockfile exists, and the process is found, but it's for ourselves, + // we clean it up. os.WriteFile("mysql.sock.lock", []byte(strconv.Itoa(os.Getpid())), 0o600) + assert.NoError(t, cleanupLockfile("mysql.sock", ts)) + assert.NoFileExists(t, "mysql.sock.lock") + + // If the lockfile exists, and the process is found, we don't clean it up. + os.WriteFile("mysql.sock.lock", []byte(strconv.Itoa(os.Getppid())), 0o600) assert.Error(t, cleanupLockfile("mysql.sock", ts)) assert.FileExists(t, "mysql.sock.lock") }