2 * src/command.c - type representing a command.
\r
4 * Copyright 2008,2009 Martin Quinson, Malek Cherier All right reserved.
\r
6 * This program is free software; you can redistribute it and/or modify it
\r
7 * under the terms of the license (GNU LGPL) which comes with this package.
\r
10 * This file contains all the definitions of the functions related with
\r
11 * the tesh command type.
\r
15 #include <command.h>
\r
16 #include <context.h>
\r
22 #include <sys/types.h>
\r
23 #include <sys/wait.h>
\r
24 #include <sys/stat.h>
\r
27 char *
\r tow32cmd(const char *cmd)
\r
29 \rstatic char w32cmd[PATH_MAX + 1] = { 0 };
30 \rchar cmd_buf[PATH_MAX + 1] = { 0 };
41 \rstrcpy(w32cmd, cmd);
48 \rif (cmd[i] != ' ' && cmd[i] != '\t' && cmd[i] != '>')
49 \rcmd_buf[j++] = cmd[i];
55 \r\r_fullpath(w32cmd, cmd_buf, sizeof(w32cmd));
56 \r\rif (!strstr(w32cmd, ".exe"))
57 \rstrcat(w32cmd, ".exe ");
58 \r\rstrcat(w32cmd, cmd + i);
60 /*printf("w32cmd : %s", w32cmd); */
\r
69 #include <xsignal.h>
\r
72 \rXBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
73 \r\rstatic void *
\r command_start(void *p);
75 command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
\r
78 \r\rcommand = xbt_new0(s_command_t, 1);
80 /* get the context of the execution of the command */
\r
81 if (!(command->context = context_dup(context)))
87 /* the exit code of the command is indefinite */
\r
88 command->exit_code = INDEFINITE;
90 /* the signal of the command is indefinite */
\r
91 command->signal = INDEFINITE_SIGNAL;
92 \r\rcommand->failed = 0;
93 \rcommand->interrupted = 0;
95 /* the mutex used to safetly access to the command unit properties */
\r
96 command->mutex = mutex;
97 \r\rcommand->output = xbt_strbuff_new();
98 \r\rcommand->pid = INDEFINITE_PID;
99 \r\rcommand->stat_val = -1;
101 /* set the unit of the command */
\r
102 command->root = unit->root ? unit->root : unit;
103 \rcommand->unit = unit;
105 /* all the commands are runned in a thread */
\r
106 command->thread = NULL;
107 \r\rcommand->successeded = 0;
108 \r\rcommand->reader = reader_new(command);
109 \r\rif (context->input->used)
110 \rcommand->writer = writer_new(command);
113 \rcommand->writer = NULL;
114 \r\rif (context->timeout != INDEFINITE)
115 \rcommand->timer = timer_new(command);
118 \rcommand->timer = NULL;
119 \r\rcommand->status = cs_initialized;
120 \rcommand->reason = csr_unknown;
121 \r\rcommand->stdin_fd = INDEFINITE_FD;
122 \rcommand->stdout_fd = INDEFINITE_FD;
124 /* register the command */
\r
125 xbt_os_mutex_acquire(mutex);
126 \r\rxbt_dynar_push(unit->commands, &command);
127 \rcommand->root->cmd_nb++;
128 \rxbt_os_mutex_release(mutex);
132 \rcommand->execlp_errno = 0;
138 \r\rint
\r command_run(command_t command)
\r
140 \rif (!silent_flag && !interrupted)
141 \rINFO2("[%s] %s", command->context->pos,
142 command->context->command_line);
143 \r\rif (!just_print_flag)
148 /* start the command in a thread */
\r
149 if (command->context->async)
152 xbt_os_thread_create("", command_start, command);
158 /* start the command in the main thread */
\r
159 command_start(command);
165 \rcommand_interrupt(command);
171 \r\rstatic void *
\r command_start(void *p)
\r
173 \rcommand_t command = (command_t) p;
174 \runit_t root = command->root;
176 /* the command is started */
\r
177 command->status = cs_started;
179 /* increment the number of started commands of the unit */
\r
180 xbt_os_mutex_acquire(command->mutex);
181 \r(root->started_cmd_nb)++;
182 \rxbt_os_mutex_release(command->mutex);
184 /* execute the command of the test */
\r
187 command_exec(command, command->context->command_line);
190 /* play the translated command line on Windows */
\r
191 command_exec(command, command->context->t_command_line);
194 \rif (cs_in_progress == command->status)
197 /* wait the process if it is in progress */
\r
198 command_wait(command);
199 \r\rif (cs_failed != command->status
200 && cs_interrupted != command->status)
201 \rcommand_check(command);
203 \r\rxbt_os_mutex_acquire(command->mutex);
205 /* if it's the last command of the root unit */
\r
206 if (!root->interrupted && root->parsed
207 && (root->started_cmd_nb ==
208 (root->failed_cmd_nb + root->interrupted_cmd_nb +
209 root->successeded_cmd_nb)))
212 /* first release the mutex */
\r
214 \rxbt_os_mutex_release(command->mutex);
216 /* the last command release the unit */
\r
217 xbt_os_sem_release(root->sem);
221 \rxbt_os_mutex_release(command->mutex);
223 /* wait the end of the timer, the reader and the writer */
\r
224 if (command->timer && command->timer->thread)
225 \rtimer_wait(command->timer);
227 /* wait the end of the writer */
\r
228 if (command->writer && command->writer->thread)
229 \rwriter_wait(command->writer);
231 /* wait the end of the reader */
\r
232 if (command->reader && command->reader->thread)
233 \rreader_wait(command->reader);
241 #define BUFSIZE 4096
\r
243 void
\r command_exec(command_t command, const char *command_line)
\r
245 \r\rSTARTUPINFO si = {
246 0}; /* contains the informations about the child process windows */
247 \rPROCESS_INFORMATION pi = {
248 0}; /* contains child process informations */
249 \rSECURITY_ATTRIBUTES sa = {
250 0}; /* contains the security descriptor for the pipe handles */
251 \rHANDLE child_stdin_handle[2] = {
252 NULL}; /* child_stdin_handle[1] <-> stdout of the child process */
253 \rHANDLE child_stdout_handle[2] = {
254 NULL}; /* child_stdout_handle[0] <-> stdin of the child process */
255 \rHANDLE child_stderr = NULL;
256 \r\r\rsa.nLength = sizeof(SECURITY_ATTRIBUTES);
257 \rsa.lpSecurityDescriptor = NULL; /* use default security for the pipe handles */
258 \r\rsa.bInheritHandle = TRUE; /* the pipe handles can be inherited */
260 (&(child_stdin_handle[0]), &(child_stdin_handle[1]), &sa, 0))
262 \rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
263 command->context->command_line,
264 error_to_string((int) GetLastError(), 0));
265 \r\runit_set_error(command->unit, (int) GetLastError(), 0,
266 command->context->pos);
267 \r\rcommand->failed = 1;
268 \rcommand->status = cs_failed;
271 \r\r\rif (!DuplicateHandle
272 (GetCurrentProcess(), (child_stdin_handle[1]),
273 GetCurrentProcess(), &(child_stderr), 0, TRUE,
274 DUPLICATE_SAME_ACCESS))
276 \rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
277 command->context->command_line,
278 error_to_string((int) GetLastError(), 0));
279 \r\runit_set_error(command->unit, (int) GetLastError(), 0,
280 command->context->pos);
281 \r\rCloseHandle(child_stdin_handle[0]);
282 \rCloseHandle(child_stdin_handle[1]);
283 \r\rcommand->failed = 1;
284 \rcommand->status = cs_failed;
288 (&(child_stdout_handle[0]), &(child_stdout_handle[1]), &sa, 0))
290 \rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
291 command->context->command_line,
292 error_to_string((int) GetLastError(), 0));
293 \runit_set_error(command->unit, (int) GetLastError(), 0,
294 command->context->pos);
295 \r\rCloseHandle(child_stdout_handle[0]);
296 \rCloseHandle(child_stdout_handle[1]);
297 \rCloseHandle(child_stdin_handle[0]);
298 \rCloseHandle(child_stdin_handle[1]);
299 \r\rcommand->failed = 1;
300 \rcommand->status = cs_failed;
304 /* Read handle for read operations on the child std output. */
\r
306 (GetCurrentProcess(), (child_stdin_handle[0]),
307 GetCurrentProcess(), &(command->stdout_fd), 0, FALSE,
308 DUPLICATE_SAME_ACCESS))
310 \rCloseHandle(child_stdout_handle[0]);
311 \rCloseHandle(child_stdout_handle[1]);
312 \rCloseHandle(child_stdin_handle[0]);
313 \rCloseHandle(child_stdin_handle[1]);
314 \r\rcommand->failed = 1;
315 \rcommand->status = cs_failed;
316 \r\rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
317 command->context->command_line,
318 error_to_string((int) GetLastError(), 0));
319 \runit_set_error(command->unit, (int) GetLastError(), 0,
320 command->context->pos);
324 /* Write handle for write operations on the child std input. */
\r
326 (GetCurrentProcess(), (child_stdout_handle[1]),
327 GetCurrentProcess(), &(command->stdin_fd), 0, FALSE,
328 DUPLICATE_SAME_ACCESS))
330 \rCloseHandle(child_stdout_handle[0]);
331 \rCloseHandle(child_stdout_handle[1]);
332 \rCloseHandle(child_stdin_handle[0]);
333 \rCloseHandle(child_stdin_handle[1]);
334 \r\rcommand->failed = 1;
335 \rcommand->status = cs_failed;
336 \r\rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
337 command->context->command_line,
338 error_to_string((int) GetLastError(), 0));
339 \r\runit_set_error(command->unit, (int) GetLastError(), 0,
340 command->context->pos);
343 \r\rCloseHandle(child_stdin_handle[0]);
344 \rCloseHandle(child_stdout_handle[1]);
345 \r\r\rif (command->timer)
348 /* launch the timer */
\r
349 timer_time(command->timer);
351 \r\rif (command->reader)
354 /* launch the reader */
\r
355 reader_read(command->reader);
357 \r\r\rif (command->writer)
360 /* launch the writer */
\r
361 writer_write(command->writer);
364 /* if there is a reader wait for its starting */
\r
366 \rxbt_os_sem_acquire(command->reader->started);
368 /* if there is a reader wait for its ending */
\r
370 \rxbt_os_sem_acquire(command->writer->written);
372 /* if there is a reader wait for its starting */
\r
374 \rxbt_os_sem_acquire(command->timer->started);
375 \r\rsi.cb = sizeof(STARTUPINFO);
376 \r\rsi.dwFlags |= STARTF_USESTDHANDLES;
377 \rsi.hStdOutput = child_stdin_handle[1];
378 \rsi.hStdInput = child_stdout_handle[0];
379 \rsi.hStdError = child_stderr;
381 /* launch the process */
\r
383 (
\rNULL,
\rtow32cmd(command_line),
\rNULL,
\rNULL,
\rTRUE,
384 \rCREATE_NO_WINDOW,
\rNULL,
\rNULL,
\r&si,
\r&pi)
\r)
386 \r\rif (ERROR_FILE_NOT_FOUND == GetLastError())
388 \rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
389 command->context->command_line, error_to_string(ECMDNOTFOUND,
391 \runit_set_error(command->unit, ECMDNOTFOUND, 1,
392 command->context->pos);
393 \rcommand_handle_failure(command, csr_command_not_found);
398 \rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
399 command->context->command_line,
400 error_to_string((int) GetLastError(), 0));
401 \r\runit_set_error(command->unit, (int) GetLastError(), 0,
402 command->context->pos);
403 \rcommand_handle_failure(command,
404 csr_create_process_function_failure);
410 /* the command is running */
\r
411 command->status = cs_in_progress;
413 /* save the pid of the command */
\r
414 command->pid = pi.hProcess;
416 /* close non used thread handle */
\r
417 CloseHandle(pi.hThread);
420 /* close non used handles */
\r
421 CloseHandle(child_stdin_handle[1]);
422 \rCloseHandle(child_stdout_handle[0]);
423 \rCloseHandle(child_stderr);
428 void
\r command_exec(command_t command, const char *command_line)
\r
430 \rint child_stdin_fd[2];
431 \rint child_stdout_fd[2];
435 is_cmd(command->unit->runner->path, command->unit->runner->builtin,
439 \r\rif (rv == EINVAL)
441 \rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
442 command->context->command_line, error_to_string(rv, 0));
443 \runit_set_error(command->unit, rv, 0, command->context->pos);
448 \rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
449 command->context->command_line, error_to_string(rv, 1));
450 \runit_set_error(command->unit, rv, 1, command->context->pos);
452 \r\rcommand_handle_failure(command, csr_command_not_found);
457 \r\rif (command->writer)
459 \rif (pipe(child_stdin_fd))
461 \rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
462 command->context->command_line, error_to_string(errno, 0));
463 \r\runit_set_error(command->unit, errno, 0, command->context->pos);
464 \r\rcommand_handle_failure(command, csr_pipe_function_failed);
468 \r\rif (command->reader)
470 \rif (pipe(child_stdout_fd))
472 \rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
473 command->context->command_line, error_to_string(errno, 0));
474 \r\rif (command->writer)
476 \rclose(child_stdin_fd[0]);
477 \rclose(child_stdin_fd[1]);
479 \r\runit_set_error(command->unit, errno, 0, command->context->pos);
480 \r\rcommand_handle_failure(command, csr_pipe_function_failed);
484 \r\rif (command->writer)
487 (child_stdin_fd[1], F_SETFL,
488 fcntl(child_stdin_fd[1], F_GETFL) | O_NONBLOCK) < 0)
490 \r\rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
491 command->context->command_line, error_to_string(errno, 0));
492 \r\rclose(child_stdin_fd[0]);
493 \rclose(child_stdin_fd[1]);
494 \r\rif (command->reader)
496 \rclose(child_stdout_fd[0]);
497 \rclose(child_stdout_fd[1]);
499 \r\runit_set_error(command->unit, errno, 0, command->context->pos);
500 \r\rcommand_handle_failure(command, csr_fcntl_function_failed);
505 /* to write to the child stdin */
\r
506 command->stdin_fd = child_stdin_fd[1];
508 /* to read from the child stdout */
\r
509 command->stdout_fd = child_stdout_fd[0];
511 /* launch the reader if any */
\r
513 \rreader_read(command->reader);
515 /* launch the writer if any */
\r
517 \rwriter_write(command->writer);
519 /* launch the timer if any */
\r
521 \rtimer_time(command->timer);
523 /* if there is a reader wait for its starting */
\r
525 \rxbt_os_sem_acquire(command->reader->started);
527 /* if there is a reader wait for its ending */
\r
529 \rxbt_os_sem_acquire(command->writer->written);
531 /* if there is a reader wait for its starting */
\r
533 \rxbt_os_sem_acquire(command->timer->started);
535 /* update the state of the command, assume it is in progress */
\r
536 command->status = cs_in_progress;
537 \r\rcommand->pid = fork();
538 \r\rif (command->pid < 0)
540 \rif (command->writer)
542 \rclose(child_stdin_fd[0]);
543 \rclose(child_stdin_fd[1]);
545 \r\rif (command->reader)
547 \rclose(child_stdout_fd[0]);
548 \rclose(child_stdout_fd[1]);
550 \r\rERROR2("[%s] Cannot fork the command `%s'", command->context->pos,
551 command->context->command_line);
552 \runit_set_error(command->unit, errno, 0, command->context->pos);
553 \rcommand_handle_failure(command, csr_fork_function_failure);
561 /* close unused file descriptors */
\r
563 \rclose(child_stdin_fd[0]);
564 \r\rif (command->reader)
565 \rclose(child_stdout_fd[1]);
571 /* close unused file descriptors */
\r
573 \rclose(child_stdin_fd[1]);
574 \r\rif (command->reader)
575 \rclose(child_stdout_fd[0]);
576 \r\rif (command->writer)
579 /* redirect stdin to child_stdin_fd[0] (now fgets(), getchar() ... read from the pipe */
\r
580 if (dup2(child_stdin_fd[0], STDIN_FILENO) < 0)
582 \rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
583 command->context->command_line, error_to_string(errno,
585 \rcommand->unit->exit_code = errno;
586 \r\runit_set_error(command->unit, errno, 0, command->context->pos);
587 \rcommand_handle_failure(command, csr_dup2_function_failure);
590 /* close the unused file descriptor */
\r
591 close(child_stdin_fd[0]);
593 \r\rif (command->reader)
596 /* redirect stdout and stderr to child_stdout_fd[1] (now printf(), perror()... write to the pipe */
\r
597 if (dup2(child_stdout_fd[1], STDOUT_FILENO) < 0)
599 \rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
600 command->context->command_line, error_to_string(errno,
602 \r\runit_set_error(command->unit, errno, 0, command->context->pos);
603 \rcommand_handle_failure(command, csr_dup2_function_failure);
605 \r\rif (dup2(child_stdout_fd[1], STDERR_FILENO) < 0)
607 \rERROR3("[%s] `%s' : NOK (%s)", command->context->pos,
608 command->context->command_line, error_to_string(errno,
610 \runit_set_error(command->unit, errno, 0, command->context->pos);
611 \rcommand_handle_failure(command, csr_dup2_function_failure);
614 /* close the unused file descriptor */
\r
615 close(child_stdout_fd[1]);
618 /* launch the command */
\r
620 ("/bin/sh", "sh", "-c", command->context->command_line,
622 \rcommand->execlp_errno = errno;
631 void
\r command_wait(command_t command)
\r
634 /* wait for the command terminaison */
\r
636 \r\rif (WAIT_FAILED == WaitForSingleObject(command->pid, INFINITE))
638 \rERROR2("[%s] Cannot wait for the child`%s'", command->context->pos,
639 command->context->command_line);
640 \r\runit_set_error(command->unit, (int) GetLastError(), 0,
641 command->context->pos);
642 \r\rcommand_handle_failure(command, csr_wait_failure);
644 /* TODO : see for the interruption */
\r
650 /* don't take care of the timer or the writer or the reader failue */
\r
651 if (cs_failed != command->status
652 && cs_interrupted != command->status)
654 \rif (!GetExitCodeProcess(command->pid, &rv))
656 \rERROR2("[%s] Cannot get the exit code of the process `%s'",
657 command->context->pos, command->context->command_line);
658 \r\runit_set_error(command->unit, (int) GetLastError(), 0,
659 command->context->pos);
660 \r\rcommand_handle_failure(command,
661 csr_get_exit_code_process_function_failure);
665 \rcommand->stat_val = command->exit_code = rv;
672 void
\r command_wait(command_t command)
\r
674 \rif (!command->execlp_errno)
677 /* let this thread wait for the child so that the main thread can detect the timeout without blocking on the wait */
\r
678 int pid = waitpid(command->pid, &(command->stat_val), 0);
679 \r\rif (pid != command->pid)
681 \rERROR2("[%s] Cannot wait for the child`%s'", command->context->pos,
682 command->context->command_line);
683 \r\runit_set_error(command->unit, errno, 0, command->context->pos);
684 \r\rcommand_handle_failure(command, csr_waitpid_function_failure);
689 \rif (WIFEXITED(command->stat_val))
690 \rcommand->exit_code = WEXITSTATUS(command->stat_val);
696 \rERROR2("[%s] Cannot execute the command `%s'", command->context->pos,
697 command->context->command_line);
698 \r\runit_set_error(command->unit, command->execlp_errno, 0,
699 command->context->pos);
700 \r\rcommand_handle_failure(command, csr_execlp_function_failure);
706 \rvoid
\r command_check(command_t command)
\r
709 \rcs_reason_t reason;
711 /* we have a signal, store it */
\r
712 if (WIFSIGNALED(command->stat_val))
716 (WTERMSIG(command->stat_val), command->context->signal));
719 /* we have a signal and no signal is expected */
\r
720 if (WIFSIGNALED(command->stat_val) && !command->context->signal)
723 \rERROR3("[%s] `%s' : NOK (unexpected signal `%s' caught)",
724 command->context->pos, command->context->command_line,
726 \r\runit_set_error(command->unit, EUNXPSIG, 1, command->context->pos);
727 \r\rreason = csr_unexpected_signal_caught;
730 /* we have a signal that differ form the expected signal */
\r
731 if (WIFSIGNALED(command->stat_val) && command->context->signal
734 (WTERMSIG(command->stat_val), command->context->signal),
735 command->context->signal))
737 \r\rERROR4("[%s] `%s' : NOK (got signal `%s' instead of `%s')",
738 command->context->pos, command->context->command_line,
739 command->signal, command->context->signal);
743 \runit_set_error(command->unit, ESIGNOTMATCH, 1,
744 command->context->pos);
746 \r\rreason = csr_signals_dont_match;
749 /* we don't receive the expected signal */
\r
750 if (!WIFSIGNALED(command->stat_val) && command->context->signal)
752 \r\rERROR3("[%s] `%s' : NOK (expected `%s' not received)",
753 command->context->pos, command->context->command_line,
754 command->context->signal);
758 \runit_set_error(command->unit, ESIGNOTRECEIVED, 1,
759 command->context->pos);
761 \r\rreason = csr_expected_signal_not_received;
764 /* if the command exit normaly and we expect a exit code : test it */
\r
765 if (WIFEXITED(command->stat_val)
766 /* && INDEFINITE != command->context->exit_code */ )
769 /* the exit codes don't match */
\r
770 if (WEXITSTATUS(command->stat_val) != command->context->exit_code)
772 \rERROR4("[%s] %s : NOK (returned code `%d' instead `%d')",
773 command->context->pos, command->context->command_line,
774 WEXITSTATUS(command->stat_val), command->context->exit_code);
778 \runit_set_error(command->unit, EEXITCODENOTMATCH, 1,
779 command->context->pos);
781 \r\rreason = csr_exit_codes_dont_match;
785 /* make sure the reader done */
\r
786 while (!command->reader->done)
787 \rxbt_os_thread_yield();
790 CloseHandle(command->stdout_fd);
793 close(command->stdout_fd);
796 \rcommand->stdout_fd = INDEFINITE_FD;
797 \r\rxbt_strbuff_chomp(command->output);
798 \rxbt_strbuff_chomp(command->context->output);
799 \rxbt_strbuff_trim(command->output);
800 \rxbt_strbuff_trim(command->context->output);
802 && !strcmp(command->output->data, command->context->output->data))
804 \rxbt_dynar_t a = xbt_str_split(command->output->data, "\n");
805 \rchar *out = xbt_str_join(a, "\n||");
806 \rxbt_dynar_free(&a);
807 \rINFO2("Output of <%s> so far: \n||%s", command->context->pos, out);
811 /* if ouput handling flag is specified check the output */
\r
812 else if (oh_check == command->context->output_handling
815 \rif (command->output->used != command->context->output->used
816 || strcmp(command->output->data, command->context->output->data))
819 \r\r\rERROR2("[%s] `%s' : NOK (outputs mismatch):",
820 command->context->pos, command->context->command_line);
823 \runit_set_error(command->unit, EOUTPUTNOTMATCH, 1,
824 command->context->pos);
827 \r\rreason = csr_outputs_dont_match;
829 /* display the diff */
\r
831 xbt_str_diff(command->context->output->data,
832 command->output->data);
838 else if (oh_ignore == command->context->output_handling)
840 \rINFO1("(ignoring the output of <%s> as requested)",
841 command->context->line);
844 else if (oh_display == command->context->output_handling)
846 \rxbt_dynar_t a = xbt_str_split(command->output->data, "\n");
847 \rchar *out = xbt_str_join(a, "\n||");
848 \rxbt_dynar_free(&a);
849 \rINFO3("[%s] Here is the (ignored) command `%s' output: \n||%s",
850 command->context->pos, command->context->command_line, out);
855 \rxbt_os_mutex_acquire(command->mutex);
856 \r\rif (command->status != cs_interrupted)
859 /* signal the success of the command */
\r
860 command->status = cs_successeded;
861 \rcommand->successeded = 1;
863 /* increment the number of successeded command of the unit */
\r
864 (command->root->successeded_cmd_nb)++;
866 \r\rxbt_os_mutex_release(command->mutex);
871 \rcommand_handle_failure(command, reason);
877 void
\r command_kill(command_t command)
\r
879 \rif (INDEFINITE_PID != command->pid)
881 \rINFO2("[%s] Kill the process `%s'", command->context->pos,
882 command->context->command_line);
883 \rTerminateProcess(command->pid, INDEFINITE);
889 void
\r command_kill(command_t command)
\r
891 \rif (INDEFINITE_PID != command->pid)
893 \rkill(command->pid, SIGTERM);
894 \r\rif (!command->context->signal)
895 \rcommand->context->signal = strdup("SIGTERM");
896 \r\rcommand->exit_code = INDEFINITE;
897 \rcommand->killed = 1;
899 \r\rINFO2("[%s] Kill the process `%s'", command->context->pos,
900 command->context->command_line);
901 \rkill(command->pid, SIGKILL);
907 \rvoid
\r command_interrupt(command_t command)
\r
909 \rxbt_os_mutex_acquire(command->mutex);
910 \r\rif ((command->status != cs_interrupted)
911 && (command->status != cs_failed)
912 && (command->status != cs_successeded))
914 \rcommand->status = cs_interrupted;
915 \rcommand->reason = csr_interruption_request;
916 \rcommand->interrupted = 1;
917 \rcommand->unit->interrupted = 1;
918 \r\rxbt_os_mutex_acquire(command->root->mutex);
919 \r(command->root->interrupted_cmd_nb)++;
920 \rxbt_os_mutex_release(command->root->mutex);
921 \r\rif (command->pid != INDEFINITE_PID)
922 \rcommand_kill(command);
924 \r\rxbt_os_mutex_release(command->mutex);
927 \r\rvoid
\r command_summarize(command_t command)
\r
929 \rif (cs_successeded != command->status)
934 \rprintf(" <killed command>\n");
938 /* display the reason of the status of the command */
\r
939 switch (command->reason)
942 /* the function pipe or CreatePipe() fails */
\r
943 case csr_pipe_function_failed:
946 (" reason : pipe() or CreatePipe() function failed (system error)\n");
948 \r\rcase csr_shell_failed:
950 (" reason : shell failed (may be command not found)\n");
952 \r\rcase csr_get_exit_code_process_function_failure:
954 (" reason : ExitCodeProcess() function failed (system error)\n");
957 /* reader failure reasons */
\r
958 case csr_read_pipe_broken:
961 (" reason : command read pipe broken\n");
963 \r\rcase csr_read_failure:
965 (" reason : command stdout read failed\n");
968 /* writer failure reasons */
\r
969 case csr_write_failure:
972 (" reason : command stdin write failed\n");
974 \r\rcase csr_write_pipe_broken:
976 (" reason : command write pipe broken\n");
979 /* timer reason */
\r
983 (" reason : command timeouted\n");
986 /* command failure reason */
\r
987 case csr_command_not_found:
990 (" reason : command not found\n");
993 /* context failure reasons */
\r
994 case csr_exit_codes_dont_match:
997 (" reason : exit codes don't match\n");
1000 /* dup2 function failure reasons */
\r
1001 case csr_dup2_function_failure:
1004 (" reason : dup2() function failed\n");
1007 /* execlp function failure reasons */
\r
1008 case csr_execlp_function_failure:
1011 (" reason : execlp() function failed\n");
1014 /* waitpid function failure reasons */
\r
1015 case csr_waitpid_function_failure:
1018 (" reason : waitpid() function failed\n");
1021 /* CreateProcess function failure reasons */
\r
1022 case csr_create_process_function_failure:
1025 (" reason : CreateProcesss() function failed\n");
1027 \r\rcase csr_outputs_dont_match:
1032 (" reason : ouputs don't match\n");
1034 /*diff = xbt_str_diff(command->context->output->data,command->output->data);
\r
1035 printf(" output diff :\n%s\n",diff);
\r
1039 \r\rcase csr_signals_dont_match:
1041 (" reason : signals don't match\n");
1043 \r\rcase csr_unexpected_signal_caught:
1045 (" reason : unexpected signal caught\n");
1047 \r\rcase csr_expected_signal_not_received:
1049 (" reason : expected signal not receipt\n");
1052 /* system failure reasons */
\r
1053 case csr_fork_function_failure:
1056 (" reason : fork function failed\n");
1058 \r\rcase csr_wait_failure:
1060 (" reason : wait command failure\n");
1063 /* global/local interruption */
\r
1064 case csr_interruption_request:
1067 (" reason : the command receive a interruption request\n");
1072 \rprintf(" reason : unknown \n");
1075 \r\rif (csr_command_not_found != command->reason
1076 && csr_fork_function_failure != command->reason
1077 && csr_execlp_function_failure != command->reason)
1079 \rif (INDEFINITE != command->exit_code)
1081 /* the command exit code */
\r
1082 printf(" exit code : %d\n",
1083 command->exit_code);
1085 /* if an expected exit code was specified display it */
\r
1086 if (INDEFINITE != command->context->exit_code)
1087 \rprintf(" expected exit code : %d\n",
1088 command->context->exit_code);
1091 \rprintf(" no expected exit code specified\n");
1093 /* no expected signal expected */
\r
1094 if (NULL == command->context->signal)
1096 \rprintf(" no expected signal specified\n");
1097 \r\rif (command->signal)
1098 \rprintf(" but got signal : %s\n",
1102 /* if an expected exit code was specified display it */
\r
1105 \rif (NULL != command->signal)
1106 \rprintf(" signal : %s\n",
1110 \rprintf(" no signal caugth\n");
1113 /* if the command has out put and the metacommand display output is specified display it */
\r
1114 if (command->output && (0 != command->output->used)
1115 && (oh_display == command->context->output_handling))
1117 \rxbt_dynar_t a = xbt_str_split(command->output->data, "\n");
1118 \rchar *out = xbt_str_join(a, "\n||");
1119 \rxbt_dynar_free(&a);
1120 \rprintf(" output :\n||%s", out);
1125 \r}
\r\rvoid
\r command_handle_failure(command_t command, cs_reason_t reason)
\r
1127 \runit_t root = command->root;
1128 \r\rxbt_os_mutex_acquire(command->mutex);
1129 \r\rif ((command->status != cs_interrupted)
1130 && (command->status != cs_failed))
1132 \rcommand->status = cs_failed;
1133 \rcommand->reason = reason;
1134 \rcommand->failed = 1;
1135 \r\rcommand->unit->failed = 1;
1136 \r\rxbt_os_mutex_acquire(root->mutex);
1138 /* increment the number of failed command of the unit */
\r
1139 root->failed_cmd_nb++;
1141 /* if the --ignore-failures option is not specified */
\r
1142 if (!keep_going_unit_flag)
1144 \rif (!root->interrupted)
1147 /* the unit interrupted (exit for the loop) */
\r
1148 root->interrupted = 1;
1150 /* release the unit */
\r
1151 xbt_os_sem_release(root->sem);
1154 /* if the --keep-going option is not specified */
\r
1155 if (!keep_going_flag)
1160 /* request an global interruption by the runner */
\r
1163 /* release the runner */
\r
1164 xbt_os_sem_release(units_sem);
1168 \r\rxbt_os_mutex_release(root->mutex);
1170 \r\rxbt_os_mutex_release(command->mutex);
1173 \r\rint
\r command_free(command_t * ptr)
\r
1176 /* close the stdin and the stdout pipe handles */
\r
1179 if ((*ptr)->stdin_fd != INDEFINITE_FD)
1180 \rCloseHandle((*ptr)->stdin_fd);
1181 \r\rif ((*ptr)->stdout_fd != INDEFINITE_FD)
1182 \rCloseHandle((*ptr)->stdout_fd);
1185 \rif ((*ptr)->stdin_fd != INDEFINITE_FD)
1186 \rclose((*ptr)->stdin_fd);
1187 \r\rif ((*ptr)->stdout_fd != INDEFINITE_FD)
1188 \rclose((*ptr)->stdout_fd);
1191 \rif ((*ptr)->timer)
1193 \rif (timer_free(&((*ptr)->timer)) < 0)
1196 \r\rif ((*ptr)->writer)
1198 \rif (writer_free(&((*ptr)->writer)) < 0)
1201 \r\rif ((*ptr)->reader)
1203 \rif (reader_free(&((*ptr)->reader)) < 0)
1206 \r\rif ((*ptr)->output)
1207 \rxbt_strbuff_free((*ptr)->output);
1208 \r\rif ((*ptr)->context)
1210 \rif (context_free(&((*ptr)->context)) < 0)
1213 \r\rif ((*ptr)->signal)
1214 \rfree((*ptr)->signal);