4
0

test-process-list.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. /*
  2. * Copyright (c) 2015-2017 Red Hat, Inc.
  3. *
  4. * All rights reserved.
  5. *
  6. * Author: Jan Friesse (jfriesse@redhat.com)
  7. *
  8. * This software licensed under BSD license, the text of which follows:
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * - Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. * - Neither the name of the Red Hat, Inc. nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  32. * THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #include <stdio.h>
  37. #include <assert.h>
  38. #include <string.h>
  39. #include <poll.h>
  40. #include <signal.h>
  41. #include <limits.h>
  42. #include <unistd.h>
  43. #include "process-list.h"
  44. static int no_executed;
  45. static int no_finished;
  46. static void
  47. signal_handlers_register(void)
  48. {
  49. struct sigaction act;
  50. act.sa_handler = SIG_DFL;
  51. sigemptyset(&act.sa_mask);
  52. act.sa_flags = SA_RESTART;
  53. sigaction(SIGCHLD, &act, NULL);
  54. act.sa_handler = SIG_IGN;
  55. sigemptyset(&act.sa_mask);
  56. act.sa_flags = SA_RESTART;
  57. sigaction(SIGPIPE, &act, NULL);
  58. }
  59. static void
  60. plist_notify(enum process_list_notify_reason reason, const struct process_list_entry *entry,
  61. void *user_data)
  62. {
  63. assert(user_data == (void *)0x42);
  64. switch (reason) {
  65. case PROCESS_LIST_NOTIFY_REASON_EXECUTED:
  66. no_executed++;
  67. break;
  68. case PROCESS_LIST_NOTIFY_REASON_FINISHED:
  69. no_finished++;
  70. break;
  71. }
  72. }
  73. static char *
  74. find_exec_path(const char *exec)
  75. {
  76. struct stat stat_buf;
  77. char *res_path;
  78. int res;
  79. assert((res_path = malloc(PATH_MAX)) != NULL);
  80. memset(res_path, 0, PATH_MAX);
  81. res = snprintf(res_path, PATH_MAX, "/bin/%s", exec);
  82. assert(res > 0 && res < PATH_MAX);
  83. if (stat(res_path, &stat_buf) == 0 && (stat_buf.st_mode & S_IXUSR)) {
  84. return (res_path);
  85. }
  86. res = snprintf(res_path, PATH_MAX, "/usr/bin/%s", exec);
  87. assert(res > 0 && res < PATH_MAX);
  88. if (stat(res_path, &stat_buf) == 0 && (stat_buf.st_mode & S_IXUSR)) {
  89. return (res_path);
  90. }
  91. return (NULL);
  92. }
  93. int
  94. main(void)
  95. {
  96. struct process_list plist;
  97. struct process_list_entry *plist_entry;
  98. int i;
  99. int timeout;
  100. int no_repeats;
  101. char *true_path, *false_path;
  102. assert((true_path = find_exec_path("true")) != NULL);
  103. assert((false_path = find_exec_path("false")) != NULL);
  104. signal_handlers_register();
  105. process_list_init(&plist, 10, 1, plist_notify, (void *)0x42);
  106. plist_entry = process_list_add(&plist, "test name", "command");
  107. assert(plist_entry != NULL);
  108. assert(strcmp(plist_entry->name, "test name") == 0);
  109. assert(plist_entry->state == PROCESS_LIST_ENTRY_STATE_INITIALIZED);
  110. assert(plist_entry->exec_argc == 1);
  111. assert(plist_entry->exec_argv[0] != NULL && strcmp(plist_entry->exec_argv[0], "command") == 0);
  112. assert(plist_entry->exec_argv[1] == NULL);
  113. plist_entry = process_list_add(&plist, "test name", "/bin/ping -c \"host wit\\\"h space\" notaspace");
  114. assert(plist_entry != NULL);
  115. assert(strcmp(plist_entry->name, "test name") == 0);
  116. assert(plist_entry->state == PROCESS_LIST_ENTRY_STATE_INITIALIZED);
  117. assert(plist_entry->exec_argc == 4);
  118. assert(plist_entry->exec_argv[0] != NULL && strcmp(plist_entry->exec_argv[0], "/bin/ping") == 0);
  119. assert(plist_entry->exec_argv[1] != NULL && strcmp(plist_entry->exec_argv[1], "-c") == 0);
  120. assert(plist_entry->exec_argv[2] != NULL && strcmp(plist_entry->exec_argv[2], "host wit\"h space") == 0);
  121. assert(plist_entry->exec_argv[3] != NULL && strcmp(plist_entry->exec_argv[3], "notaspace") == 0);
  122. assert(plist_entry->exec_argv[4] == NULL);
  123. process_list_free(&plist);
  124. /*
  125. * Test no process
  126. */
  127. no_executed = 0;
  128. no_finished = 0;
  129. assert(process_list_exec_initialized(&plist) == 0);
  130. assert(no_executed == 0);
  131. assert(process_list_get_no_running(&plist) == 0);
  132. /*
  133. * Wait to exit
  134. */
  135. no_repeats = 10;
  136. timeout = 1000 / no_repeats;
  137. for (i = 0; i < no_repeats; i++) {
  138. assert(process_list_waitpid(&plist) == 0);
  139. if (process_list_get_no_running(&plist) > 0) {
  140. poll(NULL, 0, timeout);
  141. }
  142. }
  143. assert(process_list_waitpid(&plist) == 0);
  144. assert(process_list_get_no_running(&plist) == 0);
  145. assert(no_finished == 0);
  146. assert(process_list_get_summary_result(&plist) == 0);
  147. assert(process_list_get_summary_result_short(&plist) == 0);
  148. process_list_free(&plist);
  149. /*
  150. * Test two processes. /bin/true and /bin/false. Accumulated result should be fail
  151. */
  152. plist_entry = process_list_add(&plist, "true", true_path);
  153. assert(plist_entry != NULL);
  154. plist_entry = process_list_add(&plist, "false", false_path);
  155. assert(plist_entry != NULL);
  156. no_executed = 0;
  157. no_finished = 0;
  158. assert(process_list_exec_initialized(&plist) == 0);
  159. assert(no_executed == 2);
  160. assert(process_list_get_no_running(&plist) == 2);
  161. /*
  162. * Wait to exit
  163. */
  164. no_repeats = 10;
  165. timeout = 1000 / no_repeats;
  166. for (i = 0; i < no_repeats; i++) {
  167. assert(process_list_waitpid(&plist) == 0);
  168. if (process_list_get_no_running(&plist) > 0) {
  169. poll(NULL, 0, timeout);
  170. }
  171. }
  172. assert(process_list_waitpid(&plist) == 0);
  173. assert(process_list_get_no_running(&plist) == 0);
  174. assert(no_finished == 2);
  175. assert(process_list_get_summary_result(&plist) == 1);
  176. assert(process_list_get_summary_result_short(&plist) == 1);
  177. process_list_free(&plist);
  178. /*
  179. * Test two processes. /bin/true and one non-existing. Accumulated result should be fail
  180. */
  181. plist_entry = process_list_add(&plist, "true", true_path);
  182. assert(plist_entry != NULL);
  183. plist_entry = process_list_add(&plist, "false", "/nonexistingdir/nonexistingfile");
  184. assert(plist_entry != NULL);
  185. no_executed = 0;
  186. no_finished = 0;
  187. assert(process_list_exec_initialized(&plist) == 0);
  188. assert(no_executed == 2);
  189. assert(process_list_get_no_running(&plist) == 2);
  190. /*
  191. * Wait to exit
  192. */
  193. no_repeats = 10;
  194. timeout = 1000 / no_repeats;
  195. for (i = 0; i < no_repeats; i++) {
  196. assert(process_list_waitpid(&plist) == 0);
  197. if (process_list_get_no_running(&plist) > 0) {
  198. poll(NULL, 0, timeout);
  199. }
  200. }
  201. assert(process_list_waitpid(&plist) == 0);
  202. assert(process_list_get_no_running(&plist) == 0);
  203. assert(no_finished == 2);
  204. assert(process_list_get_summary_result(&plist) == 1);
  205. assert(process_list_get_summary_result_short(&plist) == 1);
  206. process_list_free(&plist);
  207. /*
  208. * Test three processes /bin/true. Accumulated result should be success.
  209. */
  210. plist_entry = process_list_add(&plist, "true", true_path);
  211. assert(plist_entry != NULL);
  212. plist_entry = process_list_add(&plist, "true2", true_path);
  213. assert(plist_entry != NULL);
  214. plist_entry = process_list_add(&plist, "true3", true_path);
  215. assert(plist_entry != NULL);
  216. no_executed = 0;
  217. no_finished = 0;
  218. assert(process_list_exec_initialized(&plist) == 0);
  219. assert(no_executed == 3);
  220. assert(process_list_get_no_running(&plist) == 3);
  221. /*
  222. * Wait to exit
  223. */
  224. no_repeats = 10;
  225. timeout = 1000 / no_repeats;
  226. for (i = 0; i < no_repeats; i++) {
  227. assert(process_list_waitpid(&plist) == 0);
  228. if (process_list_get_no_running(&plist) > 0) {
  229. poll(NULL, 0, timeout);
  230. }
  231. }
  232. assert(process_list_waitpid(&plist) == 0);
  233. assert(process_list_get_no_running(&plist) == 0);
  234. assert(no_finished == 3);
  235. assert(process_list_get_summary_result(&plist) == 0);
  236. assert(process_list_get_summary_result_short(&plist) == 0);
  237. process_list_free(&plist);
  238. /*
  239. * Test two processes. /bin/true and cat. Waiting for maximum of 2 sec
  240. */
  241. plist_entry = process_list_add(&plist, "true", true_path);
  242. assert(plist_entry != NULL);
  243. plist_entry = process_list_add(&plist, "cat", "/bin/cat /dev/zero");
  244. assert(plist_entry != NULL);
  245. no_executed = 0;
  246. no_finished = 0;
  247. assert(process_list_exec_initialized(&plist) == 0);
  248. assert(no_executed == 2);
  249. assert(process_list_get_no_running(&plist) == 2);
  250. poll(NULL, 0, 500);
  251. assert(process_list_waitpid(&plist) == 0);
  252. poll(NULL, 0, 500);
  253. assert(process_list_waitpid(&plist) == 0);
  254. assert(process_list_get_no_running(&plist) == 1);
  255. assert(no_finished == 1);
  256. assert(process_list_get_summary_result(&plist) == -1);
  257. assert(process_list_get_summary_result_short(&plist) == -1);
  258. process_list_move_active_entries_to_kill_list(&plist);
  259. assert(process_list_process_kill_list(&plist) == 0);
  260. poll(NULL, 0, 500);
  261. assert(process_list_process_kill_list(&plist) == 0);
  262. poll(NULL, 0, 500);
  263. assert(process_list_waitpid(&plist) == 0);
  264. assert(process_list_get_kill_list_items(&plist) == 0);
  265. assert(process_list_process_kill_list(&plist) == 0);
  266. process_list_free(&plist);
  267. /*
  268. * Test two bash proceses. One ignores INT and second ignores INT and TERM. Waiting for maximum of 2 sec
  269. */
  270. plist_entry = process_list_add(&plist, "ignoresig1", "bash -c \"trap 'echo trap' SIGINT;while true;do sleep 1;done\"");
  271. assert(plist_entry != NULL);
  272. plist_entry = process_list_add(&plist, "ignoresig2", "bash -c \"trap 'echo trap' SIGINT SIGTERM;while true;do sleep 1;done\"");
  273. assert(plist_entry != NULL);
  274. no_executed = 0;
  275. no_finished = 0;
  276. assert(process_list_exec_initialized(&plist) == 0);
  277. assert(no_executed == 2);
  278. assert(process_list_get_no_running(&plist) == 2);
  279. poll(NULL, 0, 500);
  280. assert(process_list_waitpid(&plist) == 0);
  281. assert(process_list_get_no_running(&plist) == 2);
  282. assert(no_finished == 0);
  283. assert(process_list_get_summary_result(&plist) == -1);
  284. assert(process_list_get_summary_result_short(&plist) == -1);
  285. process_list_move_active_entries_to_kill_list(&plist);
  286. assert(process_list_process_kill_list(&plist) == 0);
  287. poll(NULL, 0, 500);
  288. assert(process_list_waitpid(&plist) == 0);
  289. assert(process_list_get_kill_list_items(&plist) == 1);
  290. assert(process_list_process_kill_list(&plist) == 0);
  291. poll(NULL, 0, 500);
  292. assert(process_list_waitpid(&plist) == 0);
  293. assert(process_list_get_kill_list_items(&plist) == 0);
  294. process_list_free(&plist);
  295. /*
  296. * Test 3 processes. Test if entries are properly deallocated
  297. */
  298. process_list_init(&plist, 3, 1, plist_notify, (void *)0x42);
  299. plist_entry = process_list_add(&plist, "true", true_path);
  300. assert(plist_entry != NULL);
  301. plist_entry = process_list_add(&plist, "true2", true_path);
  302. assert(plist_entry != NULL);
  303. plist_entry = process_list_add(&plist, "true3", true_path);
  304. assert(plist_entry != NULL);
  305. plist_entry = process_list_add(&plist, "true4", true_path);
  306. assert(plist_entry == NULL);
  307. no_executed = 0;
  308. no_finished = 0;
  309. assert(process_list_exec_initialized(&plist) == 0);
  310. assert(no_executed == 3);
  311. assert(process_list_get_no_running(&plist) == 3);
  312. /*
  313. * Wait to exit
  314. */
  315. no_repeats = 10;
  316. timeout = 1000 / no_repeats;
  317. for (i = 0; i < no_repeats; i++) {
  318. assert(process_list_waitpid(&plist) == 0);
  319. if (process_list_get_no_running(&plist) > 0) {
  320. poll(NULL, 0, timeout);
  321. }
  322. }
  323. assert(process_list_waitpid(&plist) == 0);
  324. assert(process_list_get_no_running(&plist) == 0);
  325. assert(no_finished == 3);
  326. assert(process_list_get_summary_result(&plist) == 0);
  327. assert(process_list_get_summary_result_short(&plist) == 0);
  328. process_list_move_active_entries_to_kill_list(&plist);
  329. plist_entry = process_list_add(&plist, "true", true_path);
  330. assert(plist_entry != NULL);
  331. plist_entry = process_list_add(&plist, "ignoresig1", "bash -c \"trap 'echo trap' SIGINT;while true;do sleep 1;done\"");
  332. assert(plist_entry != NULL);
  333. plist_entry = process_list_add(&plist, "ignoresig2", "bash -c \"trap 'echo trap' SIGINT SIGTERM;while true;do sleep 1;done\"");
  334. assert(plist_entry != NULL);
  335. plist_entry = process_list_add(&plist, "true4", true_path);
  336. assert(plist_entry == NULL);
  337. no_executed = 0;
  338. no_finished = 0;
  339. assert(process_list_exec_initialized(&plist) == 0);
  340. assert(no_executed == 3);
  341. assert(process_list_get_no_running(&plist) == 3);
  342. poll(NULL, 0, 500);
  343. assert(process_list_waitpid(&plist) == 0);
  344. assert(process_list_get_no_running(&plist) == 2);
  345. assert(no_finished == 1);
  346. assert(process_list_get_summary_result(&plist) == -1);
  347. assert(process_list_get_summary_result_short(&plist) == -1);
  348. plist_entry = process_list_add(&plist, "true4", true_path);
  349. assert(plist_entry == NULL);
  350. process_list_move_active_entries_to_kill_list(&plist);
  351. plist_entry = process_list_add(&plist, "true4", true_path);
  352. assert(plist_entry != NULL);
  353. plist_entry = process_list_add(&plist, "true5", true_path);
  354. assert(plist_entry == NULL);
  355. assert(process_list_process_kill_list(&plist) == 0);
  356. poll(NULL, 0, 500);
  357. assert(process_list_waitpid(&plist) == 0);
  358. assert(process_list_get_kill_list_items(&plist) == 1);
  359. assert(process_list_process_kill_list(&plist) == 0);
  360. poll(NULL, 0, 500);
  361. assert(process_list_waitpid(&plist) == 0);
  362. assert(process_list_get_kill_list_items(&plist) == 0);
  363. process_list_move_active_entries_to_kill_list(&plist);
  364. assert(process_list_get_summary_result(&plist) == 0);
  365. assert(process_list_get_summary_result_short(&plist) == 0);
  366. plist_entry = process_list_add(&plist, "true", true_path);
  367. assert(plist_entry != NULL);
  368. plist_entry = process_list_add(&plist, "true2", true_path);
  369. assert(plist_entry != NULL);
  370. plist_entry = process_list_add(&plist, "true3", true_path);
  371. assert(plist_entry != NULL);
  372. plist_entry = process_list_add(&plist, "true4", true_path);
  373. assert(plist_entry == NULL);
  374. process_list_free(&plist);
  375. /*
  376. * Test 3 processes and difference between summary and short-circuit summary
  377. */
  378. process_list_init(&plist, 3, 1, plist_notify, (void *)0x42);
  379. plist_entry = process_list_add(&plist, "true", true_path);
  380. assert(plist_entry != NULL);
  381. plist_entry = process_list_add(&plist, "false", false_path);
  382. assert(plist_entry != NULL);
  383. plist_entry = process_list_add(&plist, "loop", "bash -c \"while true;do sleep 1;done\"");
  384. assert(plist_entry != NULL);
  385. plist_entry = process_list_add(&plist, "true4", true_path);
  386. assert(plist_entry == NULL);
  387. no_executed = 0;
  388. no_finished = 0;
  389. assert(process_list_exec_initialized(&plist) == 0);
  390. assert(no_executed == 3);
  391. assert(process_list_get_no_running(&plist) == 3);
  392. /*
  393. * Wait to exit
  394. */
  395. no_repeats = 10;
  396. timeout = 1000 / no_repeats;
  397. for (i = 0; i < no_repeats; i++) {
  398. assert(process_list_waitpid(&plist) == 0);
  399. if (process_list_get_no_running(&plist) > 0) {
  400. poll(NULL, 0, timeout);
  401. }
  402. }
  403. assert(process_list_waitpid(&plist) == 0);
  404. assert(process_list_get_no_running(&plist) == 1);
  405. assert(no_finished == 2);
  406. assert(process_list_get_summary_result(&plist) == -1);
  407. assert(process_list_get_summary_result_short(&plist) == 1);
  408. process_list_move_active_entries_to_kill_list(&plist);
  409. assert(process_list_process_kill_list(&plist) == 0);
  410. poll(NULL, 0, 500);
  411. assert(process_list_waitpid(&plist) == 0);
  412. assert(process_list_get_kill_list_items(&plist) == 0);
  413. process_list_free(&plist);
  414. /*
  415. * Test process_list_killall by running two bash proceses.
  416. * One ignores INT and second ignores INT and TERM. Waiting for maximum of 2 sec
  417. */
  418. plist_entry = process_list_add(&plist, "ignoresig1", "bash -c \"trap 'echo trap' SIGINT;while true;do sleep 1;done\"");
  419. assert(plist_entry != NULL);
  420. plist_entry = process_list_add(&plist, "ignoresig2", "bash -c \"trap 'echo trap' SIGINT SIGTERM;while true;do sleep 1;done\"");
  421. assert(plist_entry != NULL);
  422. no_executed = 0;
  423. no_finished = 0;
  424. assert(process_list_exec_initialized(&plist) == 0);
  425. assert(no_executed == 2);
  426. assert(process_list_get_no_running(&plist) == 2);
  427. poll(NULL, 0, 500);
  428. assert(process_list_waitpid(&plist) == 0);
  429. assert(process_list_get_no_running(&plist) == 2);
  430. assert(no_finished == 0);
  431. assert(process_list_get_summary_result(&plist) == -1);
  432. assert(process_list_get_summary_result_short(&plist) == -1);
  433. assert(process_list_killall(&plist, 2000) == 0);
  434. assert(process_list_get_kill_list_items(&plist) == 0);
  435. process_list_free(&plist);
  436. /*
  437. * Empty killall exits with sucess result
  438. */
  439. assert(process_list_killall(&plist, 2000) == 0);
  440. process_list_free(&plist);
  441. return (0);
  442. }