test-process-list.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  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 <stdio.h>
  35. #include <assert.h>
  36. #include <string.h>
  37. #include <poll.h>
  38. #include <signal.h>
  39. #include "process-list.h"
  40. static int no_executed;
  41. static int no_finished;
  42. static void
  43. signal_handlers_register(void)
  44. {
  45. struct sigaction act;
  46. act.sa_handler = SIG_DFL;
  47. sigemptyset(&act.sa_mask);
  48. act.sa_flags = SA_RESTART;
  49. sigaction(SIGCHLD, &act, NULL);
  50. act.sa_handler = SIG_IGN;
  51. sigemptyset(&act.sa_mask);
  52. act.sa_flags = SA_RESTART;
  53. sigaction(SIGPIPE, &act, NULL);
  54. }
  55. static void
  56. plist_notify(enum process_list_notify_reason reason, const struct process_list_entry *entry,
  57. void *user_data)
  58. {
  59. assert(user_data == (void *)0x42);
  60. switch (reason) {
  61. case PROCESS_LIST_NOTIFY_REASON_EXECUTED:
  62. no_executed++;
  63. break;
  64. case PROCESS_LIST_NOTIFY_REASON_FINISHED:
  65. no_finished++;
  66. break;
  67. }
  68. }
  69. int
  70. main(void)
  71. {
  72. struct process_list plist;
  73. struct process_list_entry *plist_entry;
  74. int i;
  75. int timeout;
  76. int no_repeats;
  77. signal_handlers_register();
  78. process_list_init(&plist, 10, 1, plist_notify, (void *)0x42);
  79. plist_entry = process_list_add(&plist, "test name", "command");
  80. assert(plist_entry != NULL);
  81. assert(strcmp(plist_entry->name, "test name") == 0);
  82. assert(plist_entry->state == PROCESS_LIST_ENTRY_STATE_INITIALIZED);
  83. assert(plist_entry->exec_argc == 1);
  84. assert(plist_entry->exec_argv[0] != NULL && strcmp(plist_entry->exec_argv[0], "command") == 0);
  85. assert(plist_entry->exec_argv[1] == NULL);
  86. plist_entry = process_list_add(&plist, "test name", "/bin/ping -c \"host wit\\\"h space\" notaspace");
  87. assert(plist_entry != NULL);
  88. assert(strcmp(plist_entry->name, "test name") == 0);
  89. assert(plist_entry->state == PROCESS_LIST_ENTRY_STATE_INITIALIZED);
  90. assert(plist_entry->exec_argc == 4);
  91. assert(plist_entry->exec_argv[0] != NULL && strcmp(plist_entry->exec_argv[0], "/bin/ping") == 0);
  92. assert(plist_entry->exec_argv[1] != NULL && strcmp(plist_entry->exec_argv[1], "-c") == 0);
  93. assert(plist_entry->exec_argv[2] != NULL && strcmp(plist_entry->exec_argv[2], "host wit\"h space") == 0);
  94. assert(plist_entry->exec_argv[3] != NULL && strcmp(plist_entry->exec_argv[3], "notaspace") == 0);
  95. assert(plist_entry->exec_argv[4] == NULL);
  96. process_list_free(&plist);
  97. /*
  98. * Test no process
  99. */
  100. no_executed = 0;
  101. no_finished = 0;
  102. assert(process_list_exec_initialized(&plist) == 0);
  103. assert(no_executed == 0);
  104. assert(process_list_get_no_running(&plist) == 0);
  105. /*
  106. * Wait to exit
  107. */
  108. no_repeats = 10;
  109. timeout = 1000 / no_repeats;
  110. for (i = 0; i < no_repeats; i++) {
  111. assert(process_list_waitpid(&plist) == 0);
  112. if (process_list_get_no_running(&plist) > 0) {
  113. poll(NULL, 0, timeout);
  114. }
  115. }
  116. assert(process_list_waitpid(&plist) == 0);
  117. assert(process_list_get_no_running(&plist) == 0);
  118. assert(no_finished == 0);
  119. assert(process_list_get_summary_result(&plist) == 0);
  120. assert(process_list_get_summary_result_short(&plist) == 0);
  121. process_list_free(&plist);
  122. /*
  123. * Test two processes. /bin/true and /bin/false. Accumulated result should be fail
  124. */
  125. plist_entry = process_list_add(&plist, "true", "/bin/true");
  126. assert(plist_entry != NULL);
  127. plist_entry = process_list_add(&plist, "false", "/bin/false");
  128. assert(plist_entry != NULL);
  129. no_executed = 0;
  130. no_finished = 0;
  131. assert(process_list_exec_initialized(&plist) == 0);
  132. assert(no_executed == 2);
  133. assert(process_list_get_no_running(&plist) == 2);
  134. /*
  135. * Wait to exit
  136. */
  137. no_repeats = 10;
  138. timeout = 1000 / no_repeats;
  139. for (i = 0; i < no_repeats; i++) {
  140. assert(process_list_waitpid(&plist) == 0);
  141. if (process_list_get_no_running(&plist) > 0) {
  142. poll(NULL, 0, timeout);
  143. }
  144. }
  145. assert(process_list_waitpid(&plist) == 0);
  146. assert(process_list_get_no_running(&plist) == 0);
  147. assert(no_finished == 2);
  148. assert(process_list_get_summary_result(&plist) == 1);
  149. assert(process_list_get_summary_result_short(&plist) == 1);
  150. process_list_free(&plist);
  151. /*
  152. * Test two processes. /bin/true and one non-existing. Accumulated result should be fail
  153. */
  154. plist_entry = process_list_add(&plist, "true", "/bin/true");
  155. assert(plist_entry != NULL);
  156. plist_entry = process_list_add(&plist, "false", "/nonexistingdir/nonexistingfile");
  157. assert(plist_entry != NULL);
  158. no_executed = 0;
  159. no_finished = 0;
  160. assert(process_list_exec_initialized(&plist) == 0);
  161. assert(no_executed == 2);
  162. assert(process_list_get_no_running(&plist) == 2);
  163. /*
  164. * Wait to exit
  165. */
  166. no_repeats = 10;
  167. timeout = 1000 / no_repeats;
  168. for (i = 0; i < no_repeats; i++) {
  169. assert(process_list_waitpid(&plist) == 0);
  170. if (process_list_get_no_running(&plist) > 0) {
  171. poll(NULL, 0, timeout);
  172. }
  173. }
  174. assert(process_list_waitpid(&plist) == 0);
  175. assert(process_list_get_no_running(&plist) == 0);
  176. assert(no_finished == 2);
  177. assert(process_list_get_summary_result(&plist) == 1);
  178. assert(process_list_get_summary_result_short(&plist) == 1);
  179. process_list_free(&plist);
  180. /*
  181. * Test three processes /bin/true. Accumulated result should be success.
  182. */
  183. plist_entry = process_list_add(&plist, "true", "/bin/true");
  184. assert(plist_entry != NULL);
  185. plist_entry = process_list_add(&plist, "true2", "/bin/true");
  186. assert(plist_entry != NULL);
  187. plist_entry = process_list_add(&plist, "true3", "/bin/true");
  188. assert(plist_entry != NULL);
  189. no_executed = 0;
  190. no_finished = 0;
  191. assert(process_list_exec_initialized(&plist) == 0);
  192. assert(no_executed == 3);
  193. assert(process_list_get_no_running(&plist) == 3);
  194. /*
  195. * Wait to exit
  196. */
  197. no_repeats = 10;
  198. timeout = 1000 / no_repeats;
  199. for (i = 0; i < no_repeats; i++) {
  200. assert(process_list_waitpid(&plist) == 0);
  201. if (process_list_get_no_running(&plist) > 0) {
  202. poll(NULL, 0, timeout);
  203. }
  204. }
  205. assert(process_list_waitpid(&plist) == 0);
  206. assert(process_list_get_no_running(&plist) == 0);
  207. assert(no_finished == 3);
  208. assert(process_list_get_summary_result(&plist) == 0);
  209. assert(process_list_get_summary_result_short(&plist) == 0);
  210. process_list_free(&plist);
  211. /*
  212. * Test two processes. /bin/true and cat. Waiting for maximum of 2 sec
  213. */
  214. plist_entry = process_list_add(&plist, "true", "/bin/true");
  215. assert(plist_entry != NULL);
  216. plist_entry = process_list_add(&plist, "cat", "/bin/cat /dev/zero");
  217. assert(plist_entry != NULL);
  218. no_executed = 0;
  219. no_finished = 0;
  220. assert(process_list_exec_initialized(&plist) == 0);
  221. assert(no_executed == 2);
  222. assert(process_list_get_no_running(&plist) == 2);
  223. poll(NULL, 0, 500);
  224. assert(process_list_waitpid(&plist) == 0);
  225. poll(NULL, 0, 500);
  226. assert(process_list_waitpid(&plist) == 0);
  227. assert(process_list_get_no_running(&plist) == 1);
  228. assert(no_finished == 1);
  229. assert(process_list_get_summary_result(&plist) == -1);
  230. assert(process_list_get_summary_result_short(&plist) == -1);
  231. process_list_move_active_entries_to_kill_list(&plist);
  232. assert(process_list_process_kill_list(&plist) == 0);
  233. poll(NULL, 0, 500);
  234. assert(process_list_process_kill_list(&plist) == 0);
  235. poll(NULL, 0, 500);
  236. assert(process_list_waitpid(&plist) == 0);
  237. assert(process_list_get_kill_list_items(&plist) == 0);
  238. assert(process_list_process_kill_list(&plist) == 0);
  239. process_list_free(&plist);
  240. /*
  241. * Test two bash proceses. One ignores INT and second ignores INT and TERM. Waiting for maximum of 2 sec
  242. */
  243. plist_entry = process_list_add(&plist, "ignoresig1", "bash -c \"trap 'echo trap' SIGINT;while true;do sleep 1;done\"");
  244. assert(plist_entry != NULL);
  245. plist_entry = process_list_add(&plist, "ignoresig2", "bash -c \"trap 'echo trap' SIGINT SIGTERM;while true;do sleep 1;done\"");
  246. assert(plist_entry != NULL);
  247. no_executed = 0;
  248. no_finished = 0;
  249. assert(process_list_exec_initialized(&plist) == 0);
  250. assert(no_executed == 2);
  251. assert(process_list_get_no_running(&plist) == 2);
  252. poll(NULL, 0, 500);
  253. assert(process_list_waitpid(&plist) == 0);
  254. assert(process_list_get_no_running(&plist) == 2);
  255. assert(no_finished == 0);
  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_waitpid(&plist) == 0);
  262. assert(process_list_get_kill_list_items(&plist) == 1);
  263. assert(process_list_process_kill_list(&plist) == 0);
  264. poll(NULL, 0, 500);
  265. assert(process_list_waitpid(&plist) == 0);
  266. assert(process_list_get_kill_list_items(&plist) == 0);
  267. process_list_free(&plist);
  268. /*
  269. * Test 3 processes. Test if entries are properly deallocated
  270. */
  271. process_list_init(&plist, 3, 1, plist_notify, (void *)0x42);
  272. plist_entry = process_list_add(&plist, "true", "/bin/true");
  273. assert(plist_entry != NULL);
  274. plist_entry = process_list_add(&plist, "true2", "/bin/true");
  275. assert(plist_entry != NULL);
  276. plist_entry = process_list_add(&plist, "true3", "/bin/true");
  277. assert(plist_entry != NULL);
  278. plist_entry = process_list_add(&plist, "true4", "/bin/true");
  279. assert(plist_entry == NULL);
  280. no_executed = 0;
  281. no_finished = 0;
  282. assert(process_list_exec_initialized(&plist) == 0);
  283. assert(no_executed == 3);
  284. assert(process_list_get_no_running(&plist) == 3);
  285. /*
  286. * Wait to exit
  287. */
  288. no_repeats = 10;
  289. timeout = 1000 / no_repeats;
  290. for (i = 0; i < no_repeats; i++) {
  291. assert(process_list_waitpid(&plist) == 0);
  292. if (process_list_get_no_running(&plist) > 0) {
  293. poll(NULL, 0, timeout);
  294. }
  295. }
  296. assert(process_list_waitpid(&plist) == 0);
  297. assert(process_list_get_no_running(&plist) == 0);
  298. assert(no_finished == 3);
  299. assert(process_list_get_summary_result(&plist) == 0);
  300. assert(process_list_get_summary_result_short(&plist) == 0);
  301. process_list_move_active_entries_to_kill_list(&plist);
  302. plist_entry = process_list_add(&plist, "true", "/bin/true");
  303. assert(plist_entry != NULL);
  304. plist_entry = process_list_add(&plist, "ignoresig1", "bash -c \"trap 'echo trap' SIGINT;while true;do sleep 1;done\"");
  305. assert(plist_entry != NULL);
  306. plist_entry = process_list_add(&plist, "ignoresig2", "bash -c \"trap 'echo trap' SIGINT SIGTERM;while true;do sleep 1;done\"");
  307. assert(plist_entry != NULL);
  308. plist_entry = process_list_add(&plist, "true4", "/bin/true");
  309. assert(plist_entry == NULL);
  310. no_executed = 0;
  311. no_finished = 0;
  312. assert(process_list_exec_initialized(&plist) == 0);
  313. assert(no_executed == 3);
  314. assert(process_list_get_no_running(&plist) == 3);
  315. poll(NULL, 0, 500);
  316. assert(process_list_waitpid(&plist) == 0);
  317. assert(process_list_get_no_running(&plist) == 2);
  318. assert(no_finished == 1);
  319. assert(process_list_get_summary_result(&plist) == -1);
  320. assert(process_list_get_summary_result_short(&plist) == -1);
  321. plist_entry = process_list_add(&plist, "true4", "/bin/true");
  322. assert(plist_entry == NULL);
  323. process_list_move_active_entries_to_kill_list(&plist);
  324. plist_entry = process_list_add(&plist, "true4", "/bin/true");
  325. assert(plist_entry != NULL);
  326. plist_entry = process_list_add(&plist, "true5", "/bin/true");
  327. assert(plist_entry == NULL);
  328. assert(process_list_process_kill_list(&plist) == 0);
  329. poll(NULL, 0, 500);
  330. assert(process_list_waitpid(&plist) == 0);
  331. assert(process_list_get_kill_list_items(&plist) == 1);
  332. assert(process_list_process_kill_list(&plist) == 0);
  333. poll(NULL, 0, 500);
  334. assert(process_list_waitpid(&plist) == 0);
  335. assert(process_list_get_kill_list_items(&plist) == 0);
  336. process_list_move_active_entries_to_kill_list(&plist);
  337. assert(process_list_get_summary_result(&plist) == 0);
  338. assert(process_list_get_summary_result_short(&plist) == 0);
  339. plist_entry = process_list_add(&plist, "true", "/bin/true");
  340. assert(plist_entry != NULL);
  341. plist_entry = process_list_add(&plist, "true2", "/bin/true");
  342. assert(plist_entry != NULL);
  343. plist_entry = process_list_add(&plist, "true3", "/bin/true");
  344. assert(plist_entry != NULL);
  345. plist_entry = process_list_add(&plist, "true4", "/bin/true");
  346. assert(plist_entry == NULL);
  347. process_list_free(&plist);
  348. /*
  349. * Test 3 processes and difference between summary and short-circuit summary
  350. */
  351. process_list_init(&plist, 3, 1, plist_notify, (void *)0x42);
  352. plist_entry = process_list_add(&plist, "true", "/bin/true");
  353. assert(plist_entry != NULL);
  354. plist_entry = process_list_add(&plist, "false", "/bin/false");
  355. assert(plist_entry != NULL);
  356. plist_entry = process_list_add(&plist, "loop", "bash -c \"while true;do sleep 1;done\"");
  357. assert(plist_entry != NULL);
  358. plist_entry = process_list_add(&plist, "true4", "/bin/true");
  359. assert(plist_entry == NULL);
  360. no_executed = 0;
  361. no_finished = 0;
  362. assert(process_list_exec_initialized(&plist) == 0);
  363. assert(no_executed == 3);
  364. assert(process_list_get_no_running(&plist) == 3);
  365. /*
  366. * Wait to exit
  367. */
  368. no_repeats = 10;
  369. timeout = 1000 / no_repeats;
  370. for (i = 0; i < no_repeats; i++) {
  371. assert(process_list_waitpid(&plist) == 0);
  372. if (process_list_get_no_running(&plist) > 0) {
  373. poll(NULL, 0, timeout);
  374. }
  375. }
  376. assert(process_list_waitpid(&plist) == 0);
  377. assert(process_list_get_no_running(&plist) == 1);
  378. assert(no_finished == 2);
  379. assert(process_list_get_summary_result(&plist) == -1);
  380. assert(process_list_get_summary_result_short(&plist) == 1);
  381. process_list_move_active_entries_to_kill_list(&plist);
  382. assert(process_list_process_kill_list(&plist) == 0);
  383. poll(NULL, 0, 500);
  384. assert(process_list_waitpid(&plist) == 0);
  385. assert(process_list_get_kill_list_items(&plist) == 0);
  386. process_list_free(&plist);
  387. /*
  388. * Test process_list_killall by running two bash proceses.
  389. * One ignores INT and second ignores INT and TERM. Waiting for maximum of 2 sec
  390. */
  391. plist_entry = process_list_add(&plist, "ignoresig1", "bash -c \"trap 'echo trap' SIGINT;while true;do sleep 1;done\"");
  392. assert(plist_entry != NULL);
  393. plist_entry = process_list_add(&plist, "ignoresig2", "bash -c \"trap 'echo trap' SIGINT SIGTERM;while true;do sleep 1;done\"");
  394. assert(plist_entry != NULL);
  395. no_executed = 0;
  396. no_finished = 0;
  397. assert(process_list_exec_initialized(&plist) == 0);
  398. assert(no_executed == 2);
  399. assert(process_list_get_no_running(&plist) == 2);
  400. poll(NULL, 0, 500);
  401. assert(process_list_waitpid(&plist) == 0);
  402. assert(process_list_get_no_running(&plist) == 2);
  403. assert(no_finished == 0);
  404. assert(process_list_get_summary_result(&plist) == -1);
  405. assert(process_list_get_summary_result_short(&plist) == -1);
  406. assert(process_list_killall(&plist, 2000) == 0);
  407. assert(process_list_get_kill_list_items(&plist) == 0);
  408. process_list_free(&plist);
  409. /*
  410. * Empty killall exits with sucess result
  411. */
  412. assert(process_list_killall(&plist, 2000) == 0);
  413. process_list_free(&plist);
  414. return (0);
  415. }