1 /*-------------------------------------------------------------------------
2  *
3  * kill.c
4  *	  kill()
5  *
6  * Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  *
8  *	This is a replacement version of kill for Win32 which sends
9  *	signals that the backend can recognize.
10  *
11  * IDENTIFICATION
12  *	  src/port/kill.c
13  *
14  *-------------------------------------------------------------------------
15  */
16 
17 #include "c.h"
18 
19 #ifdef WIN32
20 /* signal sending */
21 int
pgkill(int pid,int sig)22 pgkill(int pid, int sig)
23 {
24 	char		pipename[128];
25 	BYTE		sigData = sig;
26 	BYTE		sigRet = 0;
27 	DWORD		bytes;
28 
29 	/* we allow signal 0 here, but it will be ignored in pg_queue_signal */
30 	if (sig >= PG_SIGNAL_COUNT || sig < 0)
31 	{
32 		errno = EINVAL;
33 		return -1;
34 	}
35 	if (pid <= 0)
36 	{
37 		/* No support for process groups */
38 		errno = EINVAL;
39 		return -1;
40 	}
41 
42 	/* special case for SIGKILL: just ask the system to terminate the target */
43 	if (sig == SIGKILL)
44 	{
45 		HANDLE		prochandle;
46 
47 		if ((prochandle = OpenProcess(PROCESS_TERMINATE, FALSE, (DWORD) pid)) == NULL)
48 		{
49 			errno = ESRCH;
50 			return -1;
51 		}
52 		if (!TerminateProcess(prochandle, 255))
53 		{
54 			_dosmaperr(GetLastError());
55 			CloseHandle(prochandle);
56 			return -1;
57 		}
58 		CloseHandle(prochandle);
59 		return 0;
60 	}
61 	snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\pgsignal_%u", pid);
62 
63 	if (CallNamedPipe(pipename, &sigData, 1, &sigRet, 1, &bytes, 1000))
64 	{
65 		if (bytes != 1 || sigRet != sig)
66 		{
67 			errno = ESRCH;
68 			return -1;
69 		}
70 		return 0;
71 	}
72 
73 	switch (GetLastError())
74 	{
75 		case ERROR_BROKEN_PIPE:
76 		case ERROR_BAD_PIPE:
77 
78 			/*
79 			 * These arise transiently as a process is exiting.  Treat them
80 			 * like POSIX treats a zombie process, reporting success.
81 			 */
82 			return 0;
83 
84 		case ERROR_FILE_NOT_FOUND:
85 			/* pipe fully gone, so treat the process as gone */
86 			errno = ESRCH;
87 			return -1;
88 		case ERROR_ACCESS_DENIED:
89 			errno = EPERM;
90 			return -1;
91 		default:
92 			errno = EINVAL;		/* unexpected */
93 			return -1;
94 	}
95 }
96 
97 #endif
98