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
165 if(!silent_flag && !interrupted)
\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
213 command_exec(command, command->context->command_line);
\r
215 /* play the translated command line on Windows */
\r
216 command_exec(command, command->context->t_command_line);
\r
219 if(cs_in_progress == command->status)
\r
221 /* wait the process if it is in progress */
\r
222 command_wait(command);
\r
224 if(cs_failed != command->status && cs_interrupted != command->status)
\r
225 command_check(command);
\r
228 xbt_os_mutex_acquire(command->mutex);
\r
230 /* if it's the last command of the root unit */
\r
231 if(!root->interrupted && root->parsed && (root->started_cmd_nb == (root->failed_cmd_nb + root->interrupted_cmd_nb + root->successeded_cmd_nb)))
\r
233 /* first release the mutex */
\r
234 root->released = 1;
\r
235 xbt_os_mutex_release(command->mutex);
\r
236 /* the last command release the unit */
\r
237 xbt_os_sem_release(root->sem);
\r
240 xbt_os_mutex_release(command->mutex);
\r
243 /* wait the end of the timer, the reader and the writer */
\r
244 if(command->timer && command->timer->thread)
\r
245 timer_wait(command->timer);
\r
247 /* wait the end of the writer */
\r
248 if(command->writer && command->writer->thread)
\r
249 writer_wait(command->writer);
\r
251 /* wait the end of the reader */
\r
252 if(command->reader && command->reader->thread)
\r
253 reader_wait(command->reader);
\r
263 #define BUFSIZE 4096
\r
266 command_exec(command_t command, const char* command_line)
\r
269 STARTUPINFO si = {0}; /* contains the informations about the child process windows*/
\r
270 PROCESS_INFORMATION pi = {0}; /* contains child process informations */
\r
271 SECURITY_ATTRIBUTES sa = {0}; /* contains the security descriptor for the pipe handles */
\r
272 HANDLE child_stdin_handle[2] = {NULL}; /* child_stdin_handle[1] <-> stdout of the child process */
\r
273 HANDLE child_stdout_handle[2] = {NULL}; /* child_stdout_handle[0] <-> stdin of the child process */
\r
274 HANDLE child_stderr = NULL;
\r
277 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
\r
278 sa.lpSecurityDescriptor = NULL; /* use default security for the pipe handles */
\r
280 sa.bInheritHandle = TRUE; /* the pipe handles can be inherited */
\r
282 if(!CreatePipe(&(child_stdin_handle[0]),&(child_stdin_handle[1]),&sa,0))
\r
284 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
\r
286 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
288 command->failed = 1;
\r
289 command->status = cs_failed;
\r
295 if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[1]),GetCurrentProcess(),&(child_stderr),0,TRUE,DUPLICATE_SAME_ACCESS))
\r
297 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
\r
299 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
301 CloseHandle(child_stdin_handle[0]);
\r
302 CloseHandle(child_stdin_handle[1]);
\r
304 command->failed = 1;
\r
305 command->status = cs_failed;
\r
310 if(!CreatePipe(&(child_stdout_handle[0]),&(child_stdout_handle[1]),&sa,0))
\r
312 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
\r
313 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
315 CloseHandle(child_stdout_handle[0]);
\r
316 CloseHandle(child_stdout_handle[1]);
\r
317 CloseHandle(child_stdin_handle[0]);
\r
318 CloseHandle(child_stdin_handle[1]);
\r
320 command->failed = 1;
\r
321 command->status = cs_failed;
\r
326 /* Read handle for read operations on the child std output. */
\r
327 if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[0]),GetCurrentProcess(),&(command->stdout_fd),0,FALSE, DUPLICATE_SAME_ACCESS))
\r
329 CloseHandle(child_stdout_handle[0]);
\r
330 CloseHandle(child_stdout_handle[1]);
\r
331 CloseHandle(child_stdin_handle[0]);
\r
332 CloseHandle(child_stdin_handle[1]);
\r
334 command->failed = 1;
\r
335 command->status = cs_failed;
\r
337 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
\r
338 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
344 /* Write handle for write operations on the child std input. */
\r
345 if(!DuplicateHandle(GetCurrentProcess(),(child_stdout_handle[1]),GetCurrentProcess(),&(command->stdin_fd), 0,FALSE,DUPLICATE_SAME_ACCESS))
\r
347 CloseHandle(child_stdout_handle[0]);
\r
348 CloseHandle(child_stdout_handle[1]);
\r
349 CloseHandle(child_stdin_handle[0]);
\r
350 CloseHandle(child_stdin_handle[1]);
\r
352 command->failed = 1;
\r
353 command->status = cs_failed;
\r
355 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
\r
357 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
362 CloseHandle(child_stdin_handle[0]);
\r
363 CloseHandle(child_stdout_handle[1]);
\r
368 /* launch the timer */
\r
369 timer_time(command->timer);
\r
372 if(command->reader)
\r
374 /* launch the reader */
\r
375 reader_read(command->reader);
\r
379 if(command->writer)
\r
381 /* launch the writer */
\r
382 writer_write(command->writer);
\r
385 /* if there is a reader wait for its starting */
\r
386 if(command->reader)
\r
387 xbt_os_sem_acquire(command->reader->started);
\r
389 /* if there is a reader wait for its ending */
\r
390 if(command->writer)
\r
391 xbt_os_sem_acquire(command->writer->written);
\r
393 /* if there is a reader wait for its starting */
\r
395 xbt_os_sem_acquire(command->timer->started);
\r
397 si.cb = sizeof(STARTUPINFO);
\r
399 si.dwFlags |= STARTF_USESTDHANDLES;
\r
400 si.hStdOutput = child_stdin_handle[1];
\r
401 si.hStdInput = child_stdout_handle[0];
\r
402 si.hStdError = child_stderr;
\r
404 /* launch the process */
\r
407 tow32cmd(command_line),
\r
419 if(ERROR_FILE_NOT_FOUND == GetLastError())
\r
421 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(ECMDNOTFOUND, 1));
\r
422 unit_set_error(command->unit, ECMDNOTFOUND, 1, command->context->pos);
\r
423 command_handle_failure(command, csr_command_not_found);
\r
427 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
\r
429 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
430 command_handle_failure(command, csr_create_process_function_failure);
\r
436 /* the command is running */
\r
437 command->status = cs_in_progress;
\r
439 /* save the pid of the command */
\r
440 command->pid = pi.hProcess;
\r
442 /* close non used thread handle */
\r
443 CloseHandle(pi.hThread);
\r
448 /* close non used handles */
\r
449 CloseHandle(child_stdin_handle[1]);
\r
450 CloseHandle(child_stdout_handle[0]);
\r
451 CloseHandle(child_stderr);
\r
457 command_exec(command_t command, const char* command_line)
\r
459 int child_stdin_fd[2] ;
\r
460 int child_stdout_fd[2];
\r
463 int rv = is_cmd(command->unit->runner->path, command->unit->runner->builtin, command_line);
\r
470 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(rv, 0));
\r
471 unit_set_error(command->unit, rv, 0, command->context->pos);
\r
475 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(rv, 1));
\r
476 unit_set_error(command->unit, rv, 1, command->context->pos);
\r
479 command_handle_failure(command, csr_command_not_found);
\r
487 if(command->writer)
\r
489 if(pipe(child_stdin_fd))
\r
491 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
\r
493 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
495 command_handle_failure(command, csr_pipe_function_failed);
\r
503 if(command->reader)
\r
505 if(pipe(child_stdout_fd))
\r
507 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
\r
509 if(command->writer)
\r
511 close(child_stdin_fd[0]);
\r
512 close(child_stdin_fd[1]);
\r
515 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
517 command_handle_failure(command, csr_pipe_function_failed);
\r
523 if(command->writer)
\r
525 if(fcntl(child_stdin_fd[1], F_SETFL, fcntl(child_stdin_fd[1], F_GETFL) | O_NONBLOCK) < 0)
\r
528 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
\r
530 close(child_stdin_fd[0]);
\r
531 close(child_stdin_fd[1]);
\r
533 if(command->reader)
\r
535 close(child_stdout_fd[0]);
\r
536 close(child_stdout_fd[1]);
\r
539 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
541 command_handle_failure(command, csr_fcntl_function_failed);
\r
547 /* to write to the child stdin */
\r
548 command->stdin_fd = child_stdin_fd[1];
\r
550 /* to read from the child stdout */
\r
551 command->stdout_fd = child_stdout_fd[0];
\r
553 /* launch the reader if any*/
\r
554 if(command->reader)
\r
555 reader_read(command->reader);
\r
557 /* launch the writer if any */
\r
558 if(command->writer)
\r
559 writer_write(command->writer);
\r
561 /* launch the timer if any */
\r
563 timer_time(command->timer);
\r
565 /* if there is a reader wait for its starting */
\r
566 if(command->reader)
\r
567 xbt_os_sem_acquire(command->reader->started);
\r
569 /* if there is a reader wait for its ending */
\r
570 if(command->writer)
\r
571 xbt_os_sem_acquire(command->writer->written);
\r
573 /* if there is a reader wait for its starting */
\r
575 xbt_os_sem_acquire(command->timer->started);
\r
577 /* update the state of the command, assume it is in progress */
\r
578 command->status = cs_in_progress;
\r
580 command->pid= fork();
\r
582 if(command->pid < 0)
\r
584 if(command->writer)
\r
586 close(child_stdin_fd[0]);
\r
587 close(child_stdin_fd[1]);
\r
590 if(command->reader)
\r
592 close(child_stdout_fd[0]);
\r
593 close(child_stdout_fd[1]);
\r
596 ERROR2("[%s] Cannot fork the command `%s'", command->context->pos, command->context->command_line);
\r
597 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
598 command_handle_failure(command,csr_fork_function_failure);
\r
605 /* close unused file descriptors */
\r
606 if(command->writer)
\r
607 close(child_stdin_fd[0]);
\r
609 if(command->reader)
\r
610 close(child_stdout_fd[1]);
\r
615 /* close unused file descriptors */
\r
616 if(command->writer)
\r
617 close(child_stdin_fd[1]);
\r
619 if(command->reader)
\r
620 close(child_stdout_fd[0]);
\r
622 if(command->writer)
\r
624 /* redirect stdin to child_stdin_fd[0] (now fgets(), getchar() ... read from the pipe */
\r
625 if(dup2(child_stdin_fd[0],STDIN_FILENO) < 0)
\r
627 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
\r
628 command->unit->exit_code = errno;
\r
630 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
631 command_handle_failure(command,csr_dup2_function_failure);
\r
634 /* close the unused file descriptor */
\r
635 close(child_stdin_fd[0]);
\r
638 if(command->reader)
\r
641 /* redirect stdout and stderr to child_stdout_fd[1] (now printf(), perror()... write to the pipe */
\r
642 if(dup2(child_stdout_fd[1],STDOUT_FILENO) < 0)
\r
644 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
\r
646 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
647 command_handle_failure(command, csr_dup2_function_failure);
\r
650 if(dup2(child_stdout_fd[1], STDERR_FILENO) < 0)
\r
652 ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
\r
653 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
654 command_handle_failure(command, csr_dup2_function_failure);
\r
657 /* close the unused file descriptor */
\r
658 close(child_stdout_fd[1]);
\r
661 /* launch the command */
\r
662 if(execlp("/bin/sh", "sh", "-c", command->context->command_line, NULL) < 0)
\r
663 command->execlp_errno = errno;
\r
671 command_wait(command_t command)
\r
673 /* wait for the command terminaison */
\r
676 if(WAIT_FAILED == WaitForSingleObject(command->pid, INFINITE))
\r
678 ERROR2("[%s] Cannot wait for the child`%s'", command->context->pos, command->context->command_line);
\r
680 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
682 command_handle_failure(command, csr_wait_failure );
\r
683 /* TODO : see for the interruption */
\r
687 /* don't take care of the timer or the writer or the reader failue */
\r
688 if(cs_failed != command->status && cs_interrupted != command->status)
\r
690 if(!GetExitCodeProcess(command->pid,&rv))
\r
692 ERROR2("[%s] Cannot get the exit code of the process `%s'",command->context->pos, command->context->command_line);
\r
694 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
696 command_handle_failure(command, csr_get_exit_code_process_function_failure );
\r
699 command->stat_val = command->exit_code = rv;
\r
705 command_wait(command_t command)
\r
707 if(!command->execlp_errno)
\r
709 /* let this thread wait for the child so that the main thread can detect the timeout without blocking on the wait */
\r
710 int pid = waitpid(command->pid, &(command->stat_val), 0);
\r
712 if(pid != command->pid)
\r
714 ERROR2("[%s] Cannot wait for the child`%s'", command->context->pos, command->context->command_line);
\r
716 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
718 command_handle_failure(command, csr_waitpid_function_failure);
\r
722 if(WIFEXITED(command->stat_val))
\r
723 command->exit_code = WEXITSTATUS(command->stat_val);
\r
728 ERROR2("[%s] Cannot execute the command `%s'", command->context->pos, command->context->command_line);
\r
730 unit_set_error(command->unit, command->execlp_errno, 0, command->context->pos);
\r
732 command_handle_failure(command, csr_execlp_function_failure);
\r
738 command_check(command_t command)
\r
741 cs_reason_t reason;
\r
743 /* we have a signal, store it */
\r
744 if(WIFSIGNALED(command->stat_val))
\r
746 command->signal = strdup(signal_name(WTERMSIG(command->stat_val),command->context->signal));
\r
749 /* we have a signal and no signal is expected */
\r
750 if(WIFSIGNALED(command->stat_val) && !command->context->signal)
\r
753 ERROR3("[%s] `%s' : NOK (unexpected signal `%s' caught)", command->context->pos, command->context->command_line, command->signal);
\r
755 unit_set_error(command->unit, EUNXPSIG, 1, command->context->pos);
\r
757 reason = csr_unexpected_signal_caught;
\r
760 /* we have a signal that differ form the expected signal */
\r
761 if(WIFSIGNALED(command->stat_val) && command->context->signal && strcmp(signal_name(WTERMSIG(command->stat_val),command->context->signal),command->context->signal))
\r
764 ERROR4("[%s] `%s' : NOK (got signal `%s' instead of `%s')", command->context->pos, command->context->command_line, command->signal, command->context->signal);
\r
769 unit_set_error(command->unit, ESIGNOTMATCH, 1, command->context->pos);
\r
772 reason = csr_signals_dont_match;
\r
775 /* we don't receive the expected signal */
\r
776 if(!WIFSIGNALED(command->stat_val) && command->context->signal)
\r
779 ERROR3("[%s] `%s' : NOK (expected `%s' not received)", command->context->pos, command->context->command_line, command->context->signal);
\r
784 unit_set_error(command->unit, ESIGNOTRECEIVED, 1, command->context->pos);
\r
787 reason = csr_expected_signal_not_received;
\r
790 /* if the command exit normaly and we expect a exit code : test it */
\r
791 if(WIFEXITED(command->stat_val) /* && INDEFINITE != command->context->exit_code*/)
\r
793 /* the exit codes don't match */
\r
794 if(WEXITSTATUS(command->stat_val) != command->context->exit_code)
\r
796 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
801 unit_set_error(command->unit, EEXITCODENOTMATCH, 1, command->context->pos);
\r
804 reason = csr_exit_codes_dont_match;
\r
808 /* make sure the reader done */
\r
809 while(!command->reader->done)
\r
810 xbt_os_thread_yield();
\r
813 CloseHandle(command->stdout_fd);
\r
815 close(command->stdout_fd);
\r
818 command->stdout_fd = INDEFINITE_FD;
\r
820 xbt_strbuff_chomp(command->output);
\r
821 xbt_strbuff_chomp(command->context->output);
\r
822 xbt_strbuff_trim(command->output);
\r
823 xbt_strbuff_trim(command->context->output);
\r
825 if(!success && !strcmp(command->output->data, command->context->output->data))
\r
827 xbt_dynar_t a = xbt_str_split(command->output->data, "\n");
\r
828 char *out = xbt_str_join(a,"\n||");
\r
829 xbt_dynar_free(&a);
\r
830 INFO2("Output of <%s> so far: \n||%s", command->context->pos,out);
\r
833 /* if ouput handling flag is specified check the output */
\r
834 else if(oh_check == command->context->output_handling && command->reader)
\r
836 if(command->output->used != command->context->output->used || strcmp(command->output->data, command->context->output->data))
\r
841 ERROR2("[%s] `%s' : NOK (outputs mismatch):", command->context->pos, command->context->command_line);
\r
845 unit_set_error(command->unit, EOUTPUTNOTMATCH, 1, command->context->pos);
\r
849 reason = csr_outputs_dont_match;
\r
851 /* display the diff */
\r
852 diff = xbt_str_diff(command->context->output->data,command->output->data);
\r
857 else if (oh_ignore == command->context->output_handling)
\r
859 INFO1("(ignoring the output of <%s> as requested)",command->context->line);
\r
861 else if (oh_display == command->context->output_handling)
\r
863 xbt_dynar_t a = xbt_str_split(command->output->data, "\n");
\r
864 char *out = xbt_str_join(a,"\n||");
\r
865 xbt_dynar_free(&a);
\r
866 INFO3("[%s] Here is the (ignored) command `%s' output: \n||%s",command->context->pos, command->context->command_line, out);
\r
872 xbt_os_mutex_acquire(command->mutex);
\r
874 if(command->status != cs_interrupted)
\r
876 /* signal the success of the command */
\r
877 command->status = cs_successeded;
\r
878 command->successeded = 1;
\r
880 /* increment the number of successeded command of the unit */
\r
881 (command->root->successeded_cmd_nb)++;
\r
884 xbt_os_mutex_release(command->mutex);
\r
888 command_handle_failure(command, reason);
\r
894 command_kill(command_t command)
\r
896 if(INDEFINITE_PID != command->pid)
\r
898 INFO2("[%s] Kill the process `%s'", command->context->pos, command->context->command_line);
\r
899 TerminateProcess(command->pid, INDEFINITE);
\r
904 command_kill(command_t command)
\r
906 if(INDEFINITE_PID != command->pid)
\r
908 kill(command->pid,SIGTERM);
\r
910 if(!command->context->signal)
\r
911 command->context->signal = strdup("SIGTERM");
\r
913 command->exit_code = INDEFINITE;
\r
914 command->killed = 1;
\r
918 INFO2("[%s] Kill the process `%s'", command->context->pos, command->context->command_line);
\r
919 kill(command->pid,SIGKILL);
\r
927 command_interrupt(command_t command)
\r
929 xbt_os_mutex_acquire(command->mutex);
\r
931 if((command->status != cs_interrupted) && (command->status != cs_failed) && (command->status != cs_successeded))
\r
933 command->status = cs_interrupted;
\r
934 command->reason = csr_interruption_request;
\r
935 command->interrupted = 1;
\r
936 command->unit->interrupted = 1;
\r
938 xbt_os_mutex_acquire(command->root->mutex);
\r
939 (command->root->interrupted_cmd_nb)++;
\r
940 xbt_os_mutex_release(command->root->mutex);
\r
942 if(command->pid != INDEFINITE_PID)
\r
943 command_kill(command);
\r
946 xbt_os_mutex_release(command->mutex);
\r
952 command_summarize(command_t command)
\r
954 if(cs_successeded != command->status)
\r
958 if(command->killed)
\r
959 printf(" <killed command>\n");
\r
962 /* display the reason of the status of the command */
\r
963 switch(command->reason)
\r
965 /* the function pipe or CreatePipe() fails */
\r
966 case csr_pipe_function_failed :
\r
967 printf(" reason : pipe() or CreatePipe() function failed (system error)\n");
\r
970 case csr_shell_failed :
\r
971 printf(" reason : shell failed (may be command not found)\n");
\r
974 case csr_get_exit_code_process_function_failure :
\r
975 printf(" reason : ExitCodeProcess() function failed (system error)\n");
\r
978 /* reader failure reasons*/
\r
979 case csr_read_pipe_broken :
\r
980 printf(" reason : command read pipe broken\n");
\r
983 case csr_read_failure :
\r
984 printf(" reason : command stdout read failed\n");
\r
987 /* writer failure reasons */
\r
988 case csr_write_failure :
\r
989 printf(" reason : command stdin write failed\n");
\r
992 case csr_write_pipe_broken :
\r
993 printf(" reason : command write pipe broken\n");
\r
998 printf(" reason : command timeouted\n");
\r
1001 /* command failure reason */
\r
1002 case csr_command_not_found :
\r
1003 printf(" reason : command not found\n");
\r
1006 /* context failure reasons */
\r
1007 case csr_exit_codes_dont_match :
\r
1008 printf(" reason : exit codes don't match\n");
\r
1012 /* dup2 function failure reasons */
\r
1013 case csr_dup2_function_failure :
\r
1014 printf(" reason : dup2() function failed\n");
\r
1018 /* execlp function failure reasons */
\r
1019 case csr_execlp_function_failure :
\r
1020 printf(" reason : execlp() function failed\n");
\r
1024 /* waitpid function failure reasons */
\r
1025 case csr_waitpid_function_failure :
\r
1026 printf(" reason : waitpid() function failed\n");
\r
1030 /* CreateProcess function failure reasons */
\r
1031 case csr_create_process_function_failure :
\r
1032 printf(" reason : CreateProcesss() function failed\n");
\r
1036 case csr_outputs_dont_match :
\r
1039 printf(" reason : ouputs don't match\n");
\r
1040 /*diff = xbt_str_diff(command->context->output->data,command->output->data);
\r
1041 printf(" output diff :\n%s\n",diff);
\r
1047 case csr_signals_dont_match :
\r
1048 printf(" reason : signals don't match\n");
\r
1051 case csr_unexpected_signal_caught:
\r
1052 printf(" reason : unexpected signal caught\n");
\r
1055 case csr_expected_signal_not_received :
\r
1056 printf(" reason : expected signal not receipt\n");
\r
1059 /* system failure reasons */
\r
1060 case csr_fork_function_failure :
\r
1061 printf(" reason : fork function failed\n");
\r
1064 case csr_wait_failure :
\r
1065 printf(" reason : wait command failure\n");
\r
1068 /* global/local interruption */
\r
1069 case csr_interruption_request :
\r
1070 printf(" reason : the command receive a interruption request\n");
\r
1074 case csr_unknown :
\r
1075 printf(" reason : unknown \n");
\r
1079 if(csr_command_not_found != command->reason && csr_fork_function_failure != command->reason && csr_execlp_function_failure != command->reason)
\r
1081 if(INDEFINITE != command->exit_code)
\r
1082 /* the command exit code */
\r
1083 printf(" exit code : %d\n",command->exit_code);
\r
1085 /* if an expected exit code was specified display it */
\r
1086 if(INDEFINITE != command->context->exit_code)
\r
1087 printf(" expected exit code : %d\n",command->context->exit_code);
\r
1089 printf(" no expected exit code specified\n");
\r
1091 /* no expected signal expected */
\r
1092 if(NULL == command->context->signal)
\r
1094 printf(" no expected signal specified\n");
\r
1096 if(command->signal)
\r
1097 printf(" but got signal : %s\n",command->signal);
\r
1100 /* if an expected exit code was specified display it */
\r
1103 if(NULL != command->signal)
\r
1104 printf(" signal : %s\n",command->signal);
\r
1106 printf(" no signal caugth\n");
\r
1109 /* if the command has out put and the metacommand display output is specified display it */
\r
1110 if(command->output && (0 != command->output->used) && (oh_display == command->context->output_handling))
\r
1112 xbt_dynar_t a = xbt_str_split(command->output->data, "\n");
\r
1113 char *out = xbt_str_join(a,"\n||");
\r
1114 xbt_dynar_free(&a);
\r
1115 printf(" output :\n||%s",out);
\r
1124 command_handle_failure(command_t command, cs_reason_t reason)
\r
1126 unit_t root = command->root;
\r
1128 xbt_os_mutex_acquire(command->mutex);
\r
1130 if((command->status != cs_interrupted) && (command->status != cs_failed))
\r
1132 command->status = cs_failed;
\r
1133 command->reason = reason;
\r
1134 command->failed = 1;
\r
1136 command->unit->failed = 1;
\r
1138 xbt_os_mutex_acquire(root->mutex);
\r
1140 /* increment the number of failed command of the unit */
\r
1141 root->failed_cmd_nb++;
\r
1143 /* if the --ignore-failures option is not specified */
\r
1144 if(!keep_going_unit_flag)
\r
1146 if(!root->interrupted)
\r
1148 /* the unit interrupted (exit for the loop) */
\r
1149 root->interrupted = 1;
\r
1151 /* release the unit */
\r
1152 xbt_os_sem_release(root->sem);
\r
1155 /* if the --keep-going option is not specified */
\r
1156 if(!keep_going_flag)
\r
1160 /* request an global interruption by the runner */
\r
1163 /* release the runner */
\r
1164 xbt_os_sem_release(units_sem);
\r
1169 xbt_os_mutex_release(root->mutex);
\r
1172 xbt_os_mutex_release(command->mutex);
\r
1176 command_free(command_t* ptr)
\r
1178 /* close the stdin and the stdout pipe handles */
\r
1181 if((*ptr)->stdin_fd != INDEFINITE_FD)
\r
1182 CloseHandle((*ptr)->stdin_fd);
\r
1184 if((*ptr)->stdout_fd != INDEFINITE_FD)
\r
1185 CloseHandle((*ptr)->stdout_fd);
\r
1189 if((*ptr)->stdin_fd != INDEFINITE_FD)
\r
1190 close((*ptr)->stdin_fd);
\r
1192 if((*ptr)->stdout_fd != INDEFINITE_FD)
\r
1193 close((*ptr)->stdout_fd);
\r
1198 if(timer_free(&((*ptr)->timer)) < 0)
\r
1202 if((*ptr)->writer)
\r
1204 if(writer_free(&((*ptr)->writer)) < 0)
\r
1208 if((*ptr)->reader)
\r
1210 if(reader_free(&((*ptr)->reader)) < 0)
\r
1214 if((*ptr)->output)
\r
1215 xbt_strbuff_free((*ptr)->output);
\r
1217 if((*ptr)->context)
\r
1219 if(context_free(&((*ptr)->context)) < 0)
\r
1223 if((*ptr)->signal)
\r
1224 free((*ptr)->signal);
\r