Check a Process Exit with mysql_waitpid on Linux

A shutdown script sends SIGTERM and immediately moves on, with no idea whether the process actually died or is still hanging around. mysql_waitpid, oddly bundled with the MariaDB client tools, solves that one problem well: give it a PID and a wait time in seconds, and it hands back an exit status your script can act on.

Allow about ten minutes. You need a Unix-like shell and the mariadb-client package. The examples use the installed Ubuntu package version 1:10.11.14-0ubuntu0.24.04.1, whose utility reports version 1.1. No database connection is required. You should also know which account owns the process you are checking.

1. Confirm the installed name and version

Start with read-only checks. These commands do not need elevated privileges:

$ command -v mysql_waitpid
/usr/bin/mysql_waitpid
$ ls -l /usr/bin/mysql_waitpid
lrwxrwxrwx 1 root root ... /usr/bin/mysql_waitpid -> mariadb-waitpid
$ dpkg-query -W -f='${Package} ${Version}\n' mariadb-client
mariadb-client 1:10.11.14-0ubuntu0.24.04.1
$ mysql_waitpid --version
mysql_waitpid version 1.1 by Jani Tolonen

MariaDB renamed the client to mariadb-waitpid from MariaDB 10.5, while retaining mysql_waitpid as a compatibility name. On this Linux installation the old name is a symlink. Use whichever name your deployment standardises on, but do not assume both names exist on every platform.

Checkpoint: Stop here if the binary is missing or the package version is not the one you expect. Install or change packages through your normal system administration process, not through this guide.

2. Read the contract before choosing a PID

The command shape is:

mysql_waitpid [options] PID WAIT_TIME

PID and WAIT_TIME must both be positive integers. The program uses the Unix kill() system call with signal 0, then waits for the process to terminate. Signal 0 is a permission and existence probe. It does not ask the process to exit and it is not a replacement for kill, systemctl stop or a service manager.

If the process exits within the wait time, or the PID does not exist, the command returns status 0. If the process is still present when the wait expires, it returns status 1. A status of 0 therefore means that the requested end condition was observed, not that this utility terminated the process.

Signal permissions still matter. Check a process owned by the same user where possible. If the target belongs to another account, the kernel may deny the probe; using sudo can broaden access and should be an explicit operational decision. This command does not need root for ordinary same-user checks.

3. Test a process that exits normally

Use a short-lived child for a harmless smoke test. The shell records its PID, and mysql_waitpid watches it for up to three seconds:

$ sleep 1 &
$ PID=$!
$ printf 'watching PID %s\n' "$PID"
watching PID 12345
$ mysql_waitpid "$PID" 3
$ printf 'mysql_waitpid status: %s\n' "$?"
mysql_waitpid status: 0
$ wait "$PID" 2>/dev/null || true

Your PID will differ. The final wait reaps the shell child where the shell supports that distinction; it does not alter the result already returned by mysql_waitpid.

Checkpoint: Status 0 confirms that the test process was gone within the allowed interval. It does not confirm that a long-running service will stop, because this utility does not send a terminating signal.

4. Handle an absent PID

An absent process is also a successful end condition. Use a positive PID that is not currently in use on the host. A high number is only an example, so check the value in your own environment:

$ mysql_waitpid 999999 1
$ printf 'mysql_waitpid status: %s\n' "$?"
mysql_waitpid status: 0

Do not treat this result as proof that a process once existed or that a service stopped cleanly. It only says that no process matching that PID remained for the utility to wait for. PIDs are recycled, so obtain a fresh PID and check it close to the operation you are monitoring.

5. Detect a timeout without changing the process

For a process that outlives the wait, the result is status 1. This example leaves a temporary sleep running only long enough to demonstrate the boundary, then cleans it up explicitly:

$ sleep 10 &
$ PID=$!
$ mysql_waitpid "$PID" 1
$ status=$?
$ printf 'mysql_waitpid status: %s\n' "$status"
mysql_waitpid status: 1
$ kill "$PID"
$ wait "$PID" 2>/dev/null || true

Warning: The kill in this demonstration is the destructive step. Replace "$PID" only with a process you are authorised to stop. In production, use the service's documented stop and recovery procedure. If the process must remain running, omit this demonstration and leave no background test process behind.

6. Put the status in a script

Use the exit status, not the command's version or help text, as the machine-readable result. Keep the PID and timeout quoted, and reject empty variables before calling the utility:

#!/bin/sh
PID='12345'
WAIT_TIME='5'

case "$PID:$WAIT_TIME" in
    *[!0-9:]*|:*)
        printf '%s\n' 'PID and wait time must be positive integers' >&2
        exit 2
        ;;
esac

if [ "$PID" -eq 0 ] || [ "$WAIT_TIME" -eq 0 ]; then
    printf '%s\n' 'PID and wait time must be greater than zero' >&2
    exit 2
fi

if mysql_waitpid "$PID" "$WAIT_TIME"; then
    printf 'PID %s is no longer running, or was absent\n' "$PID"
else
    status=$?
    if [ "$status" -eq 1 ]; then
        printf 'PID %s did not exit within %s seconds\n' "$PID" "$WAIT_TIME" >&2
    else
        printf 'mysql_waitpid failed with status %s\n' "$status" >&2
    fi
    exit "$status"
fi

For a fixed service PID, prefer reading the service's PID file or asking its manager rather than guessing a number.

7. Use the small option set deliberately

The installed utility has three useful option groups:

There is no configuration file, database connection option or service-stop mode described by this command. If you need to stop a process, use the tool that owns its lifecycle, then use mysql_waitpid only when this wait-and-status behaviour fits the workflow.

Done means