ยปCore Development>Code coverage>PCbuild/kill_python.c

Python code coverage for PCbuild/kill_python.c

#countcontent
1n/a/*
2n/a * Helper program for killing lingering python[_d].exe processes before
3n/a * building, thus attempting to avoid build failures due to files being
4n/a * locked.
5n/a */
6n/a
7n/a#include <windows.h>
8n/a#include <wchar.h>
9n/a#include <tlhelp32.h>
10n/a#include <stdio.h>
11n/a
12n/a#pragma comment(lib, "psapi")
13n/a
14n/a#ifdef _DEBUG
15n/a#define PYTHON_EXE (L"python_d.exe")
16n/a#define PYTHON_EXE_LEN (12)
17n/a#define KILL_PYTHON_EXE (L"kill_python_d.exe")
18n/a#define KILL_PYTHON_EXE_LEN (17)
19n/a#else
20n/a#define PYTHON_EXE (L"python.exe")
21n/a#define PYTHON_EXE_LEN (10)
22n/a#define KILL_PYTHON_EXE (L"kill_python.exe")
23n/a#define KILL_PYTHON_EXE_LEN (15)
24n/a#endif
25n/a
26n/aint
27n/amain(int argc, char **argv)
28n/a{
29n/a HANDLE hp, hsp, hsm; /* process, snapshot processes, snapshot modules */
30n/a DWORD dac, our_pid;
31n/a size_t len;
32n/a wchar_t path[MAX_PATH+1];
33n/a
34n/a MODULEENTRY32W me;
35n/a PROCESSENTRY32W pe;
36n/a
37n/a me.dwSize = sizeof(MODULEENTRY32W);
38n/a pe.dwSize = sizeof(PROCESSENTRY32W);
39n/a
40n/a memset(path, 0, MAX_PATH+1);
41n/a
42n/a our_pid = GetCurrentProcessId();
43n/a
44n/a hsm = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, our_pid);
45n/a if (hsm == INVALID_HANDLE_VALUE) {
46n/a printf("CreateToolhelp32Snapshot[1] failed: %d\n", GetLastError());
47n/a return 1;
48n/a }
49n/a
50n/a if (!Module32FirstW(hsm, &me)) {
51n/a printf("Module32FirstW[1] failed: %d\n", GetLastError());
52n/a CloseHandle(hsm);
53n/a return 1;
54n/a }
55n/a
56n/a /*
57n/a * Enumerate over the modules for the current process in order to find
58n/a * kill_process[_d].exe, then take a note of the directory it lives in.
59n/a */
60n/a do {
61n/a if (_wcsnicmp(me.szModule, KILL_PYTHON_EXE, KILL_PYTHON_EXE_LEN))
62n/a continue;
63n/a
64n/a len = wcsnlen_s(me.szExePath, MAX_PATH) - KILL_PYTHON_EXE_LEN;
65n/a wcsncpy_s(path, MAX_PATH+1, me.szExePath, len);
66n/a
67n/a break;
68n/a
69n/a } while (Module32NextW(hsm, &me));
70n/a
71n/a CloseHandle(hsm);
72n/a
73n/a if (path == NULL) {
74n/a printf("failed to discern directory of running process\n");
75n/a return 1;
76n/a }
77n/a
78n/a /*
79n/a * Take a snapshot of system processes. Enumerate over the snapshot,
80n/a * looking for python processes. When we find one, verify it lives
81n/a * in the same directory we live in. If it does, kill it. If we're
82n/a * unable to kill it, treat this as a fatal error and return 1.
83n/a *
84n/a * The rationale behind this is that we're called at the start of the
85n/a * build process on the basis that we'll take care of killing any
86n/a * running instances, such that the build won't encounter permission
87n/a * denied errors during linking. If we can't kill one of the processes,
88n/a * we can't provide this assurance, and the build shouldn't start.
89n/a */
90n/a
91n/a hsp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
92n/a if (hsp == INVALID_HANDLE_VALUE) {
93n/a printf("CreateToolhelp32Snapshot[2] failed: %d\n", GetLastError());
94n/a return 1;
95n/a }
96n/a
97n/a if (!Process32FirstW(hsp, &pe)) {
98n/a printf("Process32FirstW failed: %d\n", GetLastError());
99n/a CloseHandle(hsp);
100n/a return 1;
101n/a }
102n/a
103n/a dac = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE;
104n/a do {
105n/a
106n/a /*
107n/a * XXX TODO: if we really wanted to be fancy, we could check the
108n/a * modules for all processes (not just the python[_d].exe ones)
109n/a * and see if any of our DLLs are loaded (i.e. python34[_d].dll),
110n/a * as that would also inhibit our ability to rebuild the solution.
111n/a * Not worth loosing sleep over though; for now, a simple check
112n/a * for just the python executable should be sufficient.
113n/a */
114n/a
115n/a if (_wcsnicmp(pe.szExeFile, PYTHON_EXE, PYTHON_EXE_LEN))
116n/a /* This isn't a python process. */
117n/a continue;
118n/a
119n/a /* It's a python process, so figure out which directory it's in... */
120n/a hsm = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe.th32ProcessID);
121n/a if (hsm == INVALID_HANDLE_VALUE)
122n/a /*
123n/a * If our module snapshot fails (which will happen if we don't own
124n/a * the process), just ignore it and continue. (It seems different
125n/a * versions of Windows return different values for GetLastError()
126n/a * in this situation; it's easier to just ignore it and move on vs.
127n/a * stopping the build for what could be a false positive.)
128n/a */
129n/a continue;
130n/a
131n/a if (!Module32FirstW(hsm, &me)) {
132n/a printf("Module32FirstW[2] failed: %d\n", GetLastError());
133n/a CloseHandle(hsp);
134n/a CloseHandle(hsm);
135n/a return 1;
136n/a }
137n/a
138n/a do {
139n/a if (_wcsnicmp(me.szModule, PYTHON_EXE, PYTHON_EXE_LEN))
140n/a /* Wrong module, we're looking for python[_d].exe... */
141n/a continue;
142n/a
143n/a if (_wcsnicmp(path, me.szExePath, len))
144n/a /* Process doesn't live in our directory. */
145n/a break;
146n/a
147n/a /* Python process residing in the right directory, kill it! */
148n/a hp = OpenProcess(dac, FALSE, pe.th32ProcessID);
149n/a if (!hp) {
150n/a printf("OpenProcess failed: %d\n", GetLastError());
151n/a CloseHandle(hsp);
152n/a CloseHandle(hsm);
153n/a return 1;
154n/a }
155n/a
156n/a if (!TerminateProcess(hp, 1)) {
157n/a printf("TerminateProcess failed: %d\n", GetLastError());
158n/a CloseHandle(hsp);
159n/a CloseHandle(hsm);
160n/a CloseHandle(hp);
161n/a return 1;
162n/a }
163n/a
164n/a CloseHandle(hp);
165n/a break;
166n/a
167n/a } while (Module32NextW(hsm, &me));
168n/a
169n/a CloseHandle(hsm);
170n/a
171n/a } while (Process32NextW(hsp, &pe));
172n/a
173n/a CloseHandle(hsp);
174n/a
175n/a return 0;
176n/a}
177n/a
178n/a/* vi: set ts=8 sw=4 sts=4 expandtab */