/*
 * pending_stat.c — DF-3173 creator process.
 *
 * Blocks SIGTERM (both the main thread and the helper thread inherit
 * the mask), spawns a thread that sends the process SIGTERM after
 * <delay_ms>, then issues stat(2) on <path>.  The SIGTERM pends
 * undeliverable while every thread blocks it; when the stat is blocked
 * inside autofs_trigger()'s cv_mtx_wait_sig, autofs_set_sigmask()
 * temporarily unmasks exactly {INT,TERM,HUP,KILL,QUIT}
 * (sys/vfs/autofs/autofs.c:267-291), so the pending SIGTERM interrupts
 * the wait immediately -> the creator exits the trigger via the EINTR
 * path (autofs.c:373-377) at a precise, fork-latency-independent
 * moment, dropping its request reference early — exactly like a user
 * Ctrl-C'ing a hung automount lookup.
 *
 * Build: cc -O2 -pthread -o pending_stat pending_stat.c
 * Run: ./pending_stat <path> <delay_ms>
 */
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

static void *
timer_thread(void *arg)
{
	long delay_ms = (long)(intptr_t)arg;

	usleep(delay_ms * 1000);
	kill(getpid(), SIGTERM);
	return (NULL);
}

int
main(int argc, char **argv)
{
	struct stat st;
	sigset_t set;
	pthread_t t;

	if (argc != 3) {
		fprintf(stderr, "usage: %s <path> <delay_ms>\n", argv[0]);
		return (1);
	}

	sigemptyset(&set);
	sigaddset(&set, SIGTERM);
	if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
		perror("sigprocmask");
		return (1);
	}
	if (pthread_create(&t, NULL, timer_thread,
	    (void *)(intptr_t)atoi(argv[2])) != 0) {
		fprintf(stderr, "pthread_create failed\n");
		return (1);
	}

	if (stat(argv[1], &st) == -1) {
		/* EINTR from the interrupted trigger is the expected end */
	}

	return (0);
}
