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
28 tow32cmd(const char* cmd)
\r
30 static char w32cmd[PATH_MAX + 1] = {0};
\r
31 char cmd_buf[PATH_MAX + 1] = {0};
\r
43 strcpy(w32cmd, cmd);
\r
52 if(cmd[i] != ' ' && cmd[i] != '\t' && cmd[i] != '>')
\r
53 cmd_buf[j++] = cmd[i];
\r
60 _fullpath(w32cmd, cmd_buf, sizeof(w32cmd));
\r
62 if(!strstr(w32cmd, ".exe"))
\r
63 strcat(w32cmd, ".exe ");
\r
65 strcat(w32cmd, cmd + i);
\r
68 /*printf("w32cmd : %s", w32cmd);*/
\r
76 #include <xsignal.h>
\r
80 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
\r
83 command_start(void* p);
\r
87 command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
\r
91 command = xbt_new0(s_command_t, 1);
\r
93 /* get the context of the execution of the command */
\r
94 if(!(command->context = context_dup(context)))
\r
100 /* the exit code of the command is indefinite */
\r
101 command->exit_code = INDEFINITE;
\r
103 /* the signal of the command is indefinite */
\r
104 command->signal = INDEFINITE_SIGNAL;
\r
106 command->failed = 0;
\r
107 command->interrupted = 0;
\r
109 /* the mutex used to safetly access to the command unit properties */
\r
110 command->mutex = mutex;
\r
112 command->output = xbt_strbuff_new();
\r
114 command->pid = INDEFINITE_PID;
\r
116 command->stat_val = -1;
\r
118 /* set the unit of the command */
\r
119 command->root = unit->root ? unit->root : unit;
\r
120 command->unit = unit;
\r
122 /* all the commands are runned in a thread */
\r
123 command->thread = NULL;
\r
125 command->successeded = 0;
\r
127 command->reader = reader_new(command);
\r
129 if(context->input->used)
\r
130 command->writer = writer_new(command);
\r
132 command->writer = NULL;
\r
134 if(context->timeout != INDEFINITE)
\r
135 command->timer = timer_new(command);
\r
137 command->timer = NULL;
\r
139 command->status = cs_initialized;
\r
140 command->reason = csr_unknown;
\r
142 command->stdin_fd = INDEFINITE_FD;
\r
143 command->stdout_fd = INDEFINITE_FD;
\r
146 /* register the command */
\r
147 xbt_os_mutex_acquire(mutex);
\r
149 xbt_dynar_push(unit->commands, &command);
\r
150 command->root->cmd_nb++;
\r
151 xbt_os_mutex_release(mutex);
\r
154 command->killed = 0;
\r
155 command->execlp_errno = 0;
\r
163 command_run(command_t command)
\r
166 INFO2("[%s] %s",command->context->pos, command->context->command_line);
\r
168 if(!just_print_flag)
\r
172 /* start the command in a thread*/
\r
173 if(command->context->async)
\r
175 command->thread = xbt_os_thread_create("", command_start, command);
\r
180 /* start the command in the main thread */
\r
181 command_start(command);
\r
186 command_interrupt(command);
\r
197 command_start(void* p)
\r
199 command_t command = (command_t)p;
\r
200 unit_t root = command->root;
\r
202 /* the command is started */
\r
203 command->status = cs_started;
\r
205 /* increment the number of started commands of the unit */
\r
206 xbt_os_mutex_acquire(command->mutex);
\r
207 (root->started_cmd_nb)++;
\r
208 xbt_os_mutex_release(command->mutex);
\r
210 /* execute the command of the test */
\r
211 command_exec(command, command->context->command_line);
\r
213 if(cs_in_progress == command->status)
\r
215 /* wait the process if it is in progress */
\r
216 command_wait(command);
\r
218 if(cs_failed != command->status && cs_interrupted != command->status)
\r
219 command_check(command);
\r
222 xbt_os_mutex_acquire(command->mutex);
\r
224 /* if it's the last command of the root unit */
\r
225 if(!root->interrupted && root->parsed && (root->started_cmd_nb == (root->failed_cmd_nb + root->interrupted_cmd_nb + root->successeded_cmd_nb)))
\r
227 /* first release the mutex */
\r
228 root->released = 1;
\r
229 xbt_os_mutex_release(command->mutex);
\r
230 /* the last command release the unit */
\r
231 xbt_os_sem_release(root->sem);
\r
234 xbt_os_mutex_release(command->mutex);
\r
237 /* wait the end of the timer, the reader and the writer */
\r
238 if(command->timer && command->timer->thread)
\r
239 timer_wait(command->timer);
\r
241 /* wait the end of the writer */
\r
242 if(command->writer && command->writer->thread)
\r
243 writer_wait(command->writer);
\r
245 /* wait the end of the reader */
\r
246 if(command->reader && command->reader->thread)
\r
247 reader_wait(command->reader);
\r
257 #define BUFSIZE 4096
\r
260 command_exec(command_t command, const char* command_line)
\r
263 STARTUPINFO si = {0}; /* contains the informations about the child process windows*/
\r
264 PROCESS_INFORMATION pi = {0}; /* contains child process informations */
\r
265 SECURITY_ATTRIBUTES sa = {0}; /* contains the security descriptor for the pipe handles */
\r
266 HANDLE child_stdin_handle[2] = {NULL}; /* child_stdin_handle[1] <-> stdout of the child process */
\r
267 HANDLE child_stdout_handle[2] = {NULL}; /* child_stdout_handle[0] <-> stdin of the child process */
\r
268 HANDLE child_stderr = NULL;
\r
271 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
\r
272 sa.lpSecurityDescriptor = NULL; /* use default security for the pipe handles */
\r
274 sa.bInheritHandle = TRUE; /* the pipe handles can be inherited */
\r
276 if(!CreatePipe(&(child_stdin_handle[0]),&(child_stdin_handle[1]),&sa,0))
\r
278 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
\r
280 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
282 command->failed = 1;
\r
283 command->status = cs_failed;
\r
289 if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[1]),GetCurrentProcess(),&(child_stderr),0,TRUE,DUPLICATE_SAME_ACCESS))
\r
291 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
\r
293 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
295 CloseHandle(child_stdin_handle[0]);
\r
296 CloseHandle(child_stdin_handle[1]);
\r
298 command->failed = 1;
\r
299 command->status = cs_failed;
\r
304 if(!CreatePipe(&(child_stdout_handle[0]),&(child_stdout_handle[1]),&sa,0))
\r
306 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
\r
307 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
309 CloseHandle(child_stdout_handle[0]);
\r
310 CloseHandle(child_stdout_handle[1]);
\r
311 CloseHandle(child_stdin_handle[0]);
\r
312 CloseHandle(child_stdin_handle[1]);
\r
314 command->failed = 1;
\r
315 command->status = cs_failed;
\r
320 /* Read handle for read operations on the child std output. */
\r
321 if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[0]),GetCurrentProcess(),&(command->stdout_fd),0,FALSE, DUPLICATE_SAME_ACCESS))
\r
323 CloseHandle(child_stdout_handle[0]);
\r
324 CloseHandle(child_stdout_handle[1]);
\r
325 CloseHandle(child_stdin_handle[0]);
\r
326 CloseHandle(child_stdin_handle[1]);
\r
328 command->failed = 1;
\r
329 command->status = cs_failed;
\r
331 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
\r
332 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
338 /* Write handle for write operations on the child std input. */
\r
339 if(!DuplicateHandle(GetCurrentProcess(),(child_stdout_handle[1]),GetCurrentProcess(),&(command->stdin_fd), 0,FALSE,DUPLICATE_SAME_ACCESS))
\r
341 CloseHandle(child_stdout_handle[0]);
\r
342 CloseHandle(child_stdout_handle[1]);
\r
343 CloseHandle(child_stdin_handle[0]);
\r
344 CloseHandle(child_stdin_handle[1]);
\r
346 command->failed = 1;
\r
347 command->status = cs_failed;
\r
349 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
\r
351 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
356 CloseHandle(child_stdin_handle[0]);
\r
357 CloseHandle(child_stdout_handle[1]);
\r
362 /* launch the timer */
\r
363 timer_time(command->timer);
\r
366 if(command->reader)
\r
368 /* launch the reader */
\r
369 reader_read(command->reader);
\r
373 if(command->writer)
\r
375 /* launch the writer */
\r
376 writer_write(command->writer);
\r
379 /* if there is a reader wait for its starting */
\r
380 if(command->reader)
\r
381 xbt_os_sem_acquire(command->reader->started);
\r
383 /* if there is a reader wait for its ending */
\r
384 if(command->writer)
\r
385 xbt_os_sem_acquire(command->writer->written);
\r
387 /* if there is a reader wait for its starting */
\r
389 xbt_os_sem_acquire(command->timer->started);
\r
391 si.cb = sizeof(STARTUPINFO);
\r
393 si.dwFlags |= STARTF_USESTDHANDLES;
\r
394 si.hStdOutput = child_stdin_handle[1];
\r
395 si.hStdInput = child_stdout_handle[0];
\r
396 si.hStdError = child_stderr;
\r
398 /* launch the process */
\r
401 tow32cmd(command_line),
\r
413 if(ERROR_FILE_NOT_FOUND == GetLastError())
\r
415 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(ECMDNOTFOUND, 1));
\r
416 unit_set_error(command->unit, ECMDNOTFOUND, 1, command->context->pos);
\r
417 command_handle_failure(command, csr_command_not_found);
\r
421 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
\r
423 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
424 command_handle_failure(command, csr_create_process_function_failure);
\r
430 /* the command is running */
\r
431 command->status = cs_in_progress;
\r
433 /* save the pid of the command */
\r
434 command->pid = pi.hProcess;
\r
436 /* close non used thread handle */
\r
437 CloseHandle(pi.hThread);
\r
442 /* close non used handles */
\r
443 CloseHandle(child_stdin_handle[1]);
\r
444 CloseHandle(child_stdout_handle[0]);
\r
445 CloseHandle(child_stderr);
\r
451 command_exec(command_t command, const char* command_line)
\r
453 int child_stdin_fd[2] ;
\r
454 int child_stdout_fd[2];
\r
457 int rv = is_cmd(command->unit->runner->path, command->unit->runner->builtin, command_line);
\r
464 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(rv, 0));
\r
465 unit_set_error(command->unit, rv, 0, command->context->pos);
\r
469 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(rv, 1));
\r
470 unit_set_error(command->unit, rv, 1, command->context->pos);
\r
473 command_handle_failure(command, csr_command_not_found);
\r
481 if(command->writer)
\r
483 if(pipe(child_stdin_fd))
\r
485 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
\r
487 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
489 command_handle_failure(command, csr_pipe_function_failed);
\r
497 if(command->reader)
\r
499 if(pipe(child_stdout_fd))
\r
501 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
\r
503 if(command->writer)
\r
505 close(child_stdin_fd[0]);
\r
506 close(child_stdin_fd[1]);
\r
509 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
511 command_handle_failure(command, csr_pipe_function_failed);
\r
517 if(command->writer)
\r
519 if(fcntl(child_stdin_fd[1], F_SETFL, fcntl(child_stdin_fd[1], F_GETFL) | O_NONBLOCK) < 0)
\r
522 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
\r
524 close(child_stdin_fd[0]);
\r
525 close(child_stdin_fd[1]);
\r
527 if(command->reader)
\r
529 close(child_stdout_fd[0]);
\r
530 close(child_stdout_fd[1]);
\r
533 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
535 command_handle_failure(command, csr_fcntl_function_failed);
\r
541 /* to write to the child stdin */
\r
542 command->stdin_fd = child_stdin_fd[1];
\r
544 /* to read from the child stdout */
\r
545 command->stdout_fd = child_stdout_fd[0];
\r
547 /* launch the reader if any*/
\r
548 if(command->reader)
\r
549 reader_read(command->reader);
\r
551 /* launch the writer if any */
\r
552 if(command->writer)
\r
553 writer_write(command->writer);
\r
555 /* launch the timer if any */
\r
557 timer_time(command->timer);
\r
559 /* if there is a reader wait for its starting */
\r
560 if(command->reader)
\r
561 xbt_os_sem_acquire(command->reader->started);
\r
563 /* if there is a reader wait for its ending */
\r
564 if(command->writer)
\r
565 xbt_os_sem_acquire(command->writer->written);
\r
567 /* if there is a reader wait for its starting */
\r
569 xbt_os_sem_acquire(command->timer->started);
\r
571 /* update the state of the command, assume it is in progress */
\r
572 command->status = cs_in_progress;
\r
574 command->pid= fork();
\r
576 if(command->pid < 0)
\r
578 if(command->writer)
\r
580 close(child_stdin_fd[0]);
\r
581 close(child_stdin_fd[1]);
\r
584 if(command->reader)
\r
586 close(child_stdout_fd[0]);
\r
587 close(child_stdout_fd[1]);
\r
590 ERROR2("[%s] Cannot fork the command `%s'", command->context->pos, command->context->command_line);
\r
591 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
592 command_handle_failure(command,csr_fork_function_failure);
\r
599 /* close unused file descriptors */
\r
600 if(command->writer)
\r
601 close(child_stdin_fd[0]);
\r
603 if(command->reader)
\r
604 close(child_stdout_fd[1]);
\r
609 /* close unused file descriptors */
\r
610 if(command->writer)
\r
611 close(child_stdin_fd[1]);
\r
613 if(command->reader)
\r
614 close(child_stdout_fd[0]);
\r
616 if(command->writer)
\r
618 /* redirect stdin to child_stdin_fd[0] (now fgets(), getchar() ... read from the pipe */
\r
619 if(dup2(child_stdin_fd[0],STDIN_FILENO) < 0)
\r
621 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
\r
622 command->unit->exit_code = errno;
\r
624 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
625 command_handle_failure(command,csr_dup2_function_failure);
\r
628 /* close the unused file descriptor */
\r
629 close(child_stdin_fd[0]);
\r
632 if(command->reader)
\r
635 /* redirect stdout and stderr to child_stdout_fd[1] (now printf(), perror()... write to the pipe */
\r
636 if(dup2(child_stdout_fd[1],STDOUT_FILENO) < 0)
\r
638 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
\r
640 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
641 command_handle_failure(command, csr_dup2_function_failure);
\r
644 if(dup2(child_stdout_fd[1], STDERR_FILENO) < 0)
\r
646 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
\r
647 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
648 command_handle_failure(command, csr_dup2_function_failure);
\r
651 /* close the unused file descriptor */
\r
652 close(child_stdout_fd[1]);
\r
655 /* launch the command */
\r
656 if(execlp("/bin/sh", "sh", "-c", command->context->command_line, NULL) < 0)
\r
657 command->execlp_errno = errno;
\r
665 command_wait(command_t command)
\r
667 /* wait for the command terminaison */
\r
670 if(WAIT_FAILED == WaitForSingleObject(command->pid, INFINITE))
\r
672 ERROR2("[%s] Cannot wait for the child`%s'", command->context->pos, command->context->command_line);
\r
674 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
676 command_handle_failure(command, csr_wait_failure );
\r
677 /* TODO : see for the interruption */
\r
681 /* don't take care of the timer or the writer or the reader failue */
\r
682 if(cs_failed != command->status && cs_interrupted != command->status)
\r
684 if(!GetExitCodeProcess(command->pid,&rv))
\r
686 ERROR2("[%s] Cannot get the exit code of the process `%s'",command->context->pos, command->context->command_line);
\r
688 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
690 command_handle_failure(command, csr_get_exit_code_process_function_failure );
\r
693 command->stat_val = command->exit_code = rv;
\r
699 command_wait(command_t command)
\r
701 if(!command->execlp_errno)
\r
703 /* let this thread wait for the child so that the main thread can detect the timeout without blocking on the wait */
\r
704 int pid = waitpid(command->pid, &(command->stat_val), 0);
\r
706 if(pid != command->pid)
\r
708 ERROR2("[%s] Cannot wait for the child`%s'", command->context->pos, command->context->command_line);
\r
710 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
712 command_handle_failure(command, csr_waitpid_function_failure);
\r
716 if(WIFEXITED(command->stat_val))
\r
717 command->exit_code = WEXITSTATUS(command->stat_val);
\r
722 ERROR2("[%s] Cannot execute the command `%s'", command->context->pos, command->context->command_line);
\r
724 unit_set_error(command->unit, command->execlp_errno, 0, command->context->pos);
\r
726 command_handle_failure(command, csr_execlp_function_failure);
\r
732 command_check(command_t command)
\r
735 cs_reason_t reason;
\r
737 /* we have a signal, store it */
\r
738 if(WIFSIGNALED(command->stat_val))
\r
740 command->signal = strdup(signal_name(WTERMSIG(command->stat_val),command->context->signal));
\r
743 /* we have a signal and no signal is expected */
\r
744 if(WIFSIGNALED(command->stat_val) && !command->context->signal)
\r
747 ERROR3("[%s] `%s' : NOK (unexpected signal `%s' caught)", command->context->pos, command->context->command_line, command->signal);
\r
749 unit_set_error(command->unit, EUNXPSIG, 1, command->context->pos);
\r
751 reason = csr_unexpected_signal_caught;
\r
754 /* we have a signal that differ form the expected signal */
\r
755 if(WIFSIGNALED(command->stat_val) && command->context->signal && strcmp(signal_name(WTERMSIG(command->stat_val),command->context->signal),command->context->signal))
\r
758 ERROR4("[%s] `%s' : NOK (got signal `%s' instead of `%s')", command->context->pos, command->context->command_line, command->signal, command->context->signal);
\r
763 unit_set_error(command->unit, ESIGNOTMATCH, 1, command->context->pos);
\r
766 reason = csr_signals_dont_match;
\r
769 /* we don't receipt the expected signal */
\r
770 if(!WIFSIGNALED(command->stat_val) && command->context->signal)
\r
773 ERROR3("[%s] `%s' : NOK (expected `%s' not receipt)", command->context->pos, command->context->command_line, command->context->signal);
\r
778 unit_set_error(command->unit, ESIGNOTRECEIPT, 1, command->context->pos);
\r
781 reason = csr_expected_signal_not_receipt;
\r
784 /* if the command exit normaly and we expect a exit code : test it */
\r
785 if(WIFEXITED(command->stat_val) /* && INDEFINITE != command->context->exit_code*/)
\r
787 /* the exit codes don't match */
\r
788 if(WEXITSTATUS(command->stat_val) != command->context->exit_code)
\r
790 ERROR4("[%s] %s : NOK (returned code `%d' instead `%d')", command->context->pos, command->context->command_line, WEXITSTATUS(command->stat_val), command->context->exit_code);
\r
795 unit_set_error(command->unit, EEXITCODENOTMATCH, 1, command->context->pos);
\r
798 reason = csr_exit_codes_dont_match;
\r
802 /* make sure the reader done */
\r
803 while(!command->reader->done)
\r
804 xbt_os_thread_yield();
\r
807 CloseHandle(command->stdout_fd);
\r
809 close(command->stdout_fd);
\r
812 command->stdout_fd = INDEFINITE_FD;
\r
814 xbt_strbuff_chomp(command->output);
\r
815 xbt_strbuff_chomp(command->context->output);
\r
816 xbt_strbuff_trim(command->output);
\r
817 xbt_strbuff_trim(command->context->output);
\r
821 xbt_dynar_t a = xbt_str_split(command->output->data, "\n");
\r
822 char *out = xbt_str_join(a,"\n||");
\r
823 xbt_dynar_free(&a);
\r
824 INFO2("Output of <%s> so far: \n||%s", command->context->pos,out);
\r
827 /* if ouput handling flag is specified check the output */
\r
828 else if(oh_check == command->context->output_handling && command->reader)
\r
830 if(command->output->used != command->context->output->used || strcmp(command->output->data, command->context->output->data))
\r
834 ERROR2("[%s] `%s' : NOK (outputs mismatch):", command->context->pos, command->context->command_line);
\r
838 unit_set_error(command->unit, EOUTPUTNOTMATCH, 1, command->context->pos);
\r
842 reason = csr_outputs_dont_match;
\r
844 /* display the diff */
\r
845 diff = xbt_str_diff(command->context->output->data,command->output->data);
\r
850 else if (oh_ignore == command->context->output_handling)
\r
852 INFO1("(ignoring the output of <%s> as requested)",command->context->line);
\r
854 else if (oh_display == command->context->output_handling)
\r
856 xbt_dynar_t a = xbt_str_split(command->output->data, "\n");
\r
857 char *out = xbt_str_join(a,"\n||");
\r
858 xbt_dynar_free(&a);
\r
859 INFO3("[%s] Here is the (ignored) command `%s' output: \n||%s",command->context->pos, command->context->command_line, out);
\r
865 xbt_os_mutex_acquire(command->mutex);
\r
867 if(command->status != cs_interrupted)
\r
869 /* signal the success of the command */
\r
870 command->status = cs_successeded;
\r
871 command->successeded = 1;
\r
873 /* increment the number of successeded command of the unit */
\r
874 (command->root->successeded_cmd_nb)++;
\r
877 xbt_os_mutex_release(command->mutex);
\r
881 command_handle_failure(command, reason);
\r
887 command_kill(command_t command)
\r
889 if(INDEFINITE_PID != command->pid)
\r
891 INFO2("[%s] Kill the process `%s'", command->context->pos, command->context->command_line);
\r
892 TerminateProcess(command->pid, INDEFINITE);
\r
897 command_kill(command_t command)
\r
899 if(INDEFINITE_PID != command->pid)
\r
901 kill(command->pid,SIGTERM);
\r
903 if(!command->context->signal)
\r
904 command->context->signal = strdup("SIGTERM");
\r
906 command->exit_code = INDEFINITE;
\r
907 command->killed = 1;
\r
911 INFO2("[%s] Kill the process `%s'", command->context->pos, command->context->command_line);
\r
912 kill(command->pid,SIGKILL);
\r
920 command_interrupt(command_t command)
\r
922 xbt_os_mutex_acquire(command->mutex);
\r
924 if((command->status != cs_interrupted) && (command->status != cs_failed) && (command->status != cs_successeded))
\r
926 command->status = cs_interrupted;
\r
927 command->reason = csr_interruption_request;
\r
928 command->interrupted = 1;
\r
929 command->unit->interrupted = 1;
\r
931 xbt_os_mutex_acquire(command->root->mutex);
\r
932 (command->root->interrupted_cmd_nb)++;
\r
933 xbt_os_mutex_release(command->root->mutex);
\r
935 if(command->pid != INDEFINITE_PID)
\r
936 command_kill(command);
\r
939 xbt_os_mutex_release(command->mutex);
\r
945 command_summarize(command_t command)
\r
947 if(cs_successeded != command->status)
\r
951 if(command->killed)
\r
952 printf(" <killed command>\n");
\r
955 /* display the reason of the status of the command */
\r
956 switch(command->reason)
\r
958 /* the function pipe or CreatePipe() fails */
\r
959 case csr_pipe_function_failed :
\r
960 printf(" reason : pipe() or CreatePipe() function failed (system error)\n");
\r
963 case csr_shell_failed :
\r
964 printf(" reason : shell failed (may be command not found)\n");
\r
967 case csr_get_exit_code_process_function_failure :
\r
968 printf(" reason : ExitCodeProcess() function failed (system error)\n");
\r
971 /* reader failure reasons*/
\r
972 case csr_read_pipe_broken :
\r
973 printf(" reason : command read pipe broken\n");
\r
976 case csr_read_failure :
\r
977 printf(" reason : command stdout read failed\n");
\r
980 /* writer failure reasons */
\r
981 case csr_write_failure :
\r
982 printf(" reason : command stdin write failed\n");
\r
985 case csr_write_pipe_broken :
\r
986 printf(" reason : command write pipe broken\n");
\r
991 printf(" reason : command timeouted\n");
\r
994 /* command failure reason */
\r
995 case csr_command_not_found :
\r
996 printf(" reason : command not found\n");
\r
999 /* context failure reasons */
\r
1000 case csr_exit_codes_dont_match :
\r
1001 printf(" reason : exit codes don't match\n");
\r
1005 /* dup2 function failure reasons */
\r
1006 case csr_dup2_function_failure :
\r
1007 printf(" reason : dup2() function failed\n");
\r
1011 /* execlp function failure reasons */
\r
1012 case csr_execlp_function_failure :
\r
1013 printf(" reason : execlp() function failed\n");
\r
1017 /* waitpid function failure reasons */
\r
1018 case csr_waitpid_function_failure :
\r
1019 printf(" reason : waitpid() function failed\n");
\r
1023 /* CreateProcess function failure reasons */
\r
1024 case csr_create_process_function_failure :
\r
1025 printf(" reason : CreateProcesss() function failed\n");
\r
1029 case csr_outputs_dont_match :
\r
1032 printf(" reason : ouputs don't match\n");
\r
1033 diff = xbt_str_diff(command->context->output->data,command->output->data);
\r
1034 printf(" output diff :\n%s\n",diff);
\r
1040 case csr_signals_dont_match :
\r
1041 printf(" reason : signals don't match\n");
\r
1044 case csr_unexpected_signal_caught:
\r
1045 printf(" reason : unexpected signal caught\n");
\r
1048 case csr_expected_signal_not_receipt :
\r
1049 printf(" reason : expected signal not receipt\n");
\r
1052 /* system failure reasons */
\r
1053 case csr_fork_function_failure :
\r
1054 printf(" reason : fork function failed\n");
\r
1057 case csr_wait_failure :
\r
1058 printf(" reason : wait command failure\n");
\r
1061 /* global/local interruption */
\r
1062 case csr_interruption_request :
\r
1063 printf(" reason : the command receive a interruption request\n");
\r
1067 case csr_unknown :
\r
1068 printf(" reason : unknown \n");
\r
1072 if(csr_command_not_found != command->reason && csr_fork_function_failure != command->reason && csr_execlp_function_failure != command->reason)
\r
1074 if(INDEFINITE != command->exit_code)
\r
1075 /* the command exit code */
\r
1076 printf(" exit code : %d\n",command->exit_code);
\r
1078 /* if an expected exit code was specified display it */
\r
1079 if(INDEFINITE != command->context->exit_code)
\r
1080 printf(" expected exit code : %d\n",command->context->exit_code);
\r
1082 printf(" no expected exit code specified\n");
\r
1084 /* no expected signal expected */
\r
1085 if(NULL == command->context->signal)
\r
1087 printf(" no expected signal specified\n");
\r
1089 if(command->signal)
\r
1090 printf(" but got signal : %s\n",command->signal);
\r
1093 /* if an expected exit code was specified display it */
\r
1096 if(NULL != command->signal)
\r
1097 printf(" signal : %s\n",command->signal);
\r
1099 printf(" no signal caugth\n");
\r
1102 /* if the command has out put and the metacommand display output is specified display it */
\r
1103 if(command->output && (0 != command->output->used) && (oh_display == command->context->output_handling))
\r
1105 xbt_dynar_t a = xbt_str_split(command->output->data, "\n");
\r
1106 char *out = xbt_str_join(a,"\n||");
\r
1107 xbt_dynar_free(&a);
\r
1108 printf(" output :\n||%s",out);
\r
1117 command_handle_failure(command_t command, cs_reason_t reason)
\r
1119 unit_t root = command->root;
\r
1121 xbt_os_mutex_acquire(command->mutex);
\r
1123 if((command->status != cs_interrupted) && (command->status != cs_failed))
\r
1125 command->status = cs_failed;
\r
1126 command->reason = reason;
\r
1127 command->failed = 1;
\r
1129 command->unit->failed = 1;
\r
1131 xbt_os_mutex_acquire(root->mutex);
\r
1133 /* increment the number of failed command of the unit */
\r
1134 root->failed_cmd_nb++;
\r
1136 /* if the --ignore-failures option is not specified */
\r
1137 if(!keep_going_unit_flag)
\r
1139 if(!root->interrupted)
\r
1141 /* the unit interrupted (exit for the loop) */
\r
1142 root->interrupted = 1;
\r
1144 /* release the unit */
\r
1145 xbt_os_sem_release(root->sem);
\r
1148 /* if the --keep-going option is not specified */
\r
1149 if(!keep_going_flag)
\r
1153 /* request an global interruption by the runner */
\r
1156 /* release the runner */
\r
1157 xbt_os_sem_release(units_sem);
\r
1162 xbt_os_mutex_release(root->mutex);
\r
1165 xbt_os_mutex_release(command->mutex);
\r
1169 command_free(command_t* ptr)
\r
1171 /* close the stdin and the stdout pipe handles */
\r
1174 if((*ptr)->stdin_fd != INDEFINITE_FD)
\r
1175 CloseHandle((*ptr)->stdin_fd);
\r
1177 if((*ptr)->stdout_fd != INDEFINITE_FD)
\r
1178 CloseHandle((*ptr)->stdout_fd);
\r
1182 if((*ptr)->stdin_fd != INDEFINITE_FD)
\r
1183 close((*ptr)->stdin_fd);
\r
1185 if((*ptr)->stdout_fd != INDEFINITE_FD)
\r
1186 close((*ptr)->stdout_fd);
\r
1191 if(timer_free(&((*ptr)->timer)) < 0)
\r
1195 if((*ptr)->writer)
\r
1197 if(writer_free(&((*ptr)->writer)) < 0)
\r
1201 if((*ptr)->reader)
\r
1203 if(reader_free(&((*ptr)->reader)) < 0)
\r
1207 if((*ptr)->output)
\r
1208 xbt_strbuff_free((*ptr)->output);
\r
1210 if((*ptr)->context)
\r
1212 if(context_free(&((*ptr)->context)) < 0)
\r
1216 if((*ptr)->signal)
\r
1217 free((*ptr)->signal);
\r