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
26 #include <xsignal.h>
\r
28 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
\r
31 command_start(void* p);
\r
34 command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
\r
37 /* TODO : check the parameters */
\r
39 command = xbt_new0(s_command_t, 1);
\r
41 /* get the context of the execution of the command */
\r
42 if(!(command->context = context_dup(context)))
\r
48 /* the exit code of the command is indefinite */
\r
49 command->exit_code = INDEFINITE;
\r
51 /* the signal of the command is indefinite */
\r
52 command->signal = INDEFINITE_SIGNAL;
\r
54 command->failed = 0;
\r
55 command->interrupted = 0;
\r
57 /* the mutex used to safetly access to the command unit properties */
\r
58 command->mutex = mutex;
\r
60 if(context->output->used)
\r
61 command->output = xbt_strbuff_new();
\r
63 command->output = NULL;
\r
65 command->pid = INDEFINITE_PID;
\r
67 command->stat_val = -1;
\r
69 /* set the unit of the command */
\r
70 command->unit = unit->root ? unit->root : unit;
\r
72 /* all the commands are runned in a thread */
\r
73 command->thread = NULL;
\r
75 command->successeded = 0;
\r
77 if(context->output->used)
\r
78 command->reader = reader_new(command);
\r
80 command->reader = NULL;
\r
82 if(context->input->used)
\r
83 command->writer = writer_new(command);
\r
85 command->writer = NULL;
\r
87 if(context->timeout != INDEFINITE)
\r
88 command->timer = timer_new(command);
\r
90 command->timer = NULL;
\r
92 command->status = cs_initialized;
\r
93 command->reason = csr_unknown;
\r
95 command->stdin_fd = INDEFINITE_FD;
\r
96 command->stdout_fd = INDEFINITE_FD;
\r
99 /* register the command */
\r
100 xbt_os_mutex_acquire(mutex);
\r
102 /*vector_push_back(unit->commands, command);*/
\r
103 xbt_dynar_push(unit->commands, &command);
\r
104 command->unit->cmd_nb++;
\r
105 xbt_os_mutex_release(mutex);
\r
108 command->killed = 0;
\r
109 command->execlp_errno = 0;
\r
117 command_run(command_t command)
\r
119 /* TODO : check the parameter */
\r
122 INFO1("tesh %s",command->context->command_line);
\r
124 if(!just_print_flag)
\r
128 /* start the command */
\r
130 if(command->context->async)
\r
132 command->thread = xbt_os_thread_create("", command_start, command);
\r
136 command_start(command);
\r
140 command_interrupt(command);
\r
149 command_start(void* p)
\r
151 command_t command = (command_t)p;
\r
152 unit_t unit = command->unit;
\r
154 /* the command is started */
\r
155 command->status = cs_started;
\r
157 /* increment the number of started commands of the unit */
\r
158 xbt_os_mutex_acquire(command->mutex);
\r
159 (command->unit->started_cmd_nb)++;
\r
160 xbt_os_mutex_release(command->mutex);
\r
162 /* execute the command of the test */
\r
163 command_exec(command, command->context->command_line);
\r
165 if(cs_in_progress == command->status)
\r
168 /* on attend la fin de la commande.
\r
169 * la command peut soit se terminée normalement,
\r
170 * soit se terminée à la suite d'un timeout, d'une erreur de lecture des son reader ou d'une erreur d'écriture de son writer
\r
171 * soit à la suit d'une demande d'interruption
\r
174 command_wait(command);
\r
176 if(cs_failed != command->status && cs_interrupted != command->status)
\r
177 command_check(command);
\r
180 xbt_os_mutex_acquire(command->mutex);
\r
182 /* if it's the last command release its unit */
\r
183 if(!unit->interrupted && unit->parsed && (unit->started_cmd_nb == (unit->failed_cmd_nb + unit->interrupted_cmd_nb + unit->successeded_cmd_nb)))
\r
185 /* first release the mutex */
\r
186 unit->released = 1;
\r
187 xbt_os_mutex_release(command->mutex);
\r
188 /* the last command release the unit */
\r
189 xbt_os_sem_release(command->unit->sem);
\r
192 xbt_os_mutex_release(command->mutex);
\r
195 /* wait the end of the timer, the reader and the writer */
\r
196 if(command->timer && command->timer->thread)
\r
197 timer_wait(command->timer);
\r
199 if(command->writer && command->writer->thread)
\r
200 writer_wait(command->writer);
\r
202 if(command->reader && command->reader->thread)
\r
203 reader_wait(command->reader);
\r
210 command_exec(command_t command, const char* command_line)
\r
213 STARTUPINFO si = {0}; /* contains the informations about the child process windows*/
\r
214 PROCESS_INFORMATION pi = {0}; /* contains child process informations */
\r
215 SECURITY_ATTRIBUTES sa = {0}; /* contains the security descriptor for the pipe handles */
\r
216 HANDLE child_stdin_handle[2] = {NULL}; /* child_stdin_handle[1] <-> stdout of the child process */
\r
217 HANDLE child_stdout_handle[2] = {NULL}; /* child_stdout_handle[0] <-> stdin of the child process */
\r
218 HANDLE child_stderr = NULL;
\r
220 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
\r
221 sa.lpSecurityDescriptor = NULL; /* use default security for the pipe handles */
\r
223 sa.bInheritHandle = TRUE; /* the pipe handles can be inherited */
\r
225 if(!CreatePipe(&(child_stdin_handle[0]),&(child_stdin_handle[1]),&sa,0))
\r
227 error_register("CreatePipe() function failed", (int)GetLastError(), command->context->command_line, command->unit->fstream->name);
\r
228 command->failed = 1;
\r
229 command->status = cs_failed;
\r
235 if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[1]),GetCurrentProcess(),&(child_stderr),0,TRUE,DUPLICATE_SAME_ACCESS))
\r
237 error_register("DuplicateHandle() function failed", (int)GetLastError(), command->context->command_line, command->unit->fstream->name);
\r
239 CloseHandle(child_stdin_handle[0]);
\r
240 CloseHandle(child_stdin_handle[1]);
\r
242 command->failed = 1;
\r
243 command->status = cs_failed;
\r
248 if(!CreatePipe(&(child_stdout_handle[0]),&(child_stdout_handle[1]),&sa,0))
\r
250 error_register("CreatePipe() function failed", (int)GetLastError(), command->context->command_line, command->unit->fstream->name);
\r
252 CloseHandle(child_stdout_handle[0]);
\r
253 CloseHandle(child_stdout_handle[1]);
\r
254 CloseHandle(child_stdin_handle[0]);
\r
255 CloseHandle(child_stdin_handle[1]);
\r
257 command->failed = 1;
\r
258 command->status = cs_failed;
\r
263 /* Read handle for read operations on the child std output. */
\r
264 if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[0]),GetCurrentProcess(),&(command->stdout_fd),0,FALSE, DUPLICATE_SAME_ACCESS))
\r
266 CloseHandle(child_stdout_handle[0]);
\r
267 CloseHandle(child_stdout_handle[1]);
\r
268 CloseHandle(child_stdin_handle[0]);
\r
269 CloseHandle(child_stdin_handle[1]);
\r
271 command->failed = 1;
\r
272 command->status = cs_failed;
\r
274 error_register("DuplicateHandle() function failed", (int)GetLastError(), command->context->command_line, command->unit->fstream->name);
\r
280 /* Write handle for write operations on the child std input. */
\r
281 if(!DuplicateHandle(GetCurrentProcess(),(child_stdout_handle[1]),GetCurrentProcess(),&(command->stdin_fd), 0,FALSE,DUPLICATE_SAME_ACCESS))
\r
283 CloseHandle(child_stdout_handle[0]);
\r
284 CloseHandle(child_stdout_handle[1]);
\r
285 CloseHandle(child_stdin_handle[0]);
\r
286 CloseHandle(child_stdin_handle[1]);
\r
288 command->failed = 1;
\r
289 command->status = cs_failed;
\r
291 error_register("DuplicateHandle() function failed", (int)GetLastError(), command->context->command_line, command->unit->fstream->name);
\r
296 CloseHandle(child_stdin_handle[0]);
\r
297 CloseHandle(child_stdout_handle[1]);
\r
301 /* launch the timer */
\r
302 timer_time(command->timer);
\r
305 if(command->reader)
\r
307 /* launch the reader */
\r
308 reader_read(command->reader);
\r
312 if(command->writer)
\r
314 /* launch the writer */
\r
315 writer_write(command->writer);
\r
318 si.cb = sizeof(STARTUPINFO);
\r
320 si.dwFlags |= STARTF_USESTDHANDLES;
\r
321 si.hStdOutput = child_stdin_handle[1];
\r
322 si.hStdInput = child_stdout_handle[0];
\r
323 si.hStdError = child_stderr;
\r
325 /* launch the process */
\r
328 (char*)command_line,
\r
339 error_register("CreateProcess() function failed", (int)GetLastError(), command->context->command_line, command->unit->fstream->name);
\r
340 command_handle_failure(command,csr_create_process_function_failure);
\r
344 /* the command is running */
\r
345 command->status = cs_in_progress;
\r
347 /* save the pid of the command */
\r
348 command->pid = pi.hProcess;
\r
350 /* close non used thread handle */
\r
351 CloseHandle(pi.hThread);
\r
356 /* close non used handles */
\r
357 CloseHandle(child_stdin_handle[1]);
\r
358 CloseHandle(child_stdout_handle[0]);
\r
359 CloseHandle(child_stderr);
\r
365 command_exec(command_t command, const char* command_line)
\r
367 int child_stdin_fd[2] ;
\r
368 int child_stdout_fd[2];
\r
370 if(command->writer)
\r
372 if(pipe(child_stdin_fd))
\r
374 error_register("pipe() function failed", errno, command->context->command_line, command->unit->fstream->name);
\r
375 command_handle_failure(command, csr_pipe_function_failed);
\r
381 if(command->reader)
\r
383 if(pipe(child_stdout_fd))
\r
385 error_register("write() function failed", errno, command->context->command_line, command->unit->fstream->name);
\r
387 if(command->writer)
\r
389 close(child_stdin_fd[0]);
\r
390 close(child_stdin_fd[1]);
\r
393 command_handle_failure(command, csr_pipe_function_failed);
\r
399 if(command->writer)
\r
401 if(fcntl(child_stdin_fd[1], F_SETFL, fcntl(child_stdin_fd[1], F_GETFL) | O_NONBLOCK) < 0)
\r
403 error_register("fcntl() function failed", errno, command->context->command_line, command->unit->fstream->name);
\r
405 close(child_stdin_fd[0]);
\r
406 close(child_stdin_fd[1]);
\r
408 if(command->reader)
\r
410 close(child_stdout_fd[0]);
\r
411 close(child_stdout_fd[1]);
\r
414 command_handle_failure(command, csr_fcntl_function_failed);
\r
420 /* to write to the child stdin */
\r
421 command->stdin_fd = child_stdin_fd[1];
\r
423 /* to read from the child stdout */
\r
424 command->stdout_fd = child_stdout_fd[0];
\r
426 /* launch the reader if any*/
\r
427 if(command->reader)
\r
428 reader_read(command->reader);
\r
430 /* launch the writer if any */
\r
431 if(command->writer)
\r
432 writer_write(command->writer);
\r
434 /* launch the timer if any */
\r
436 timer_time(command->timer);
\r
438 /* if there is a reader wait for its starting */
\r
439 if(command->reader)
\r
440 xbt_os_sem_acquire(command->reader->started);
\r
442 /* if there is a reader wait for its ending */
\r
443 if(command->writer)
\r
444 xbt_os_sem_acquire(command->writer->written);
\r
446 /* if there is a reader wait for its starting */
\r
448 xbt_os_sem_acquire(command->timer->started);
\r
450 /* update the state of the command, assume it is in progress */
\r
451 command->status = cs_in_progress;
\r
453 command->pid= fork();
\r
455 if(command->pid < 0)
\r
457 if(command->writer)
\r
459 close(child_stdin_fd[0]);
\r
460 close(child_stdin_fd[1]);
\r
463 if(command->reader)
\r
465 close(child_stdout_fd[0]);
\r
466 close(child_stdout_fd[1]);
\r
469 error_register("fcntl() function failed", errno, command->context->command_line, command->unit->fstream->name);
\r
470 command_handle_failure(command,csr_fork_function_failure);
\r
477 /* close unused file descriptors */
\r
478 if(command->writer)
\r
479 close(child_stdin_fd[0]);
\r
481 if(command->reader)
\r
482 close(child_stdout_fd[1]);
\r
487 /* close unused file descriptors */
\r
488 if(command->writer)
\r
489 close(child_stdin_fd[1]);
\r
491 if(command->reader)
\r
492 close(child_stdout_fd[0]);
\r
494 if(command->writer)
\r
496 /* redirect stdin to child_stdin_fd[0] (now fgets(), getchar() ... read from the pipe */
\r
497 if(dup2(child_stdin_fd[0],STDIN_FILENO) < 0)
\r
499 error_register("dup2() function failed", errno, command->context->command_line, command->unit->fstream->name);
\r
500 command_handle_failure(command,csr_dup2_function_failure);
\r
503 /* close the unused file descriptor */
\r
504 close(child_stdin_fd[0]);
\r
507 if(command->reader)
\r
510 /* redirect stdout and stderr to child_stdout_fd[1] (now printf(), perror()... write to the pipe */
\r
511 if(dup2(child_stdout_fd[1],STDOUT_FILENO) < 0)
\r
513 error_register("dup2() function failed", errno, command->context->command_line, command->unit->fstream->name);
\r
514 command_handle_failure(command, csr_dup2_function_failure);
\r
517 if(dup2(child_stdout_fd[1], STDERR_FILENO) < 0)
\r
519 error_register("dup2() function failed", errno, command->context->command_line, command->unit->fstream->name);
\r
520 command_handle_failure(command, csr_dup2_function_failure);
\r
523 /* close the unused file descriptor */
\r
524 close(child_stdout_fd[1]);
\r
527 /* launch the command */
\r
528 if(execlp("/bin/sh", "sh", "-c", command->context->command_line, NULL) < 0)
\r
529 command->execlp_errno = errno;
\r
537 command_wait(command_t command)
\r
539 /* wait for the command terminaison */
\r
542 if(WAIT_FAILED == WaitForSingleObject(command->pid, INFINITE))
\r
544 ERROR0("WaitForSingleObject() failed");
\r
545 /* TODO : see for the interruption */
\r
549 /* don't take care of the timer or the writer or the reader failue */
\r
550 if(cs_failed != command->status && cs_interrupted != command->status)
\r
552 if(!GetExitCodeProcess(command->pid,&rv))
\r
554 ERROR1("GetExitCodeProcess() failed for the child %s",command->context->command_line);
\r
555 /* TODO : see for the interruption */
\r
558 command->stat_val = command->exit_code = rv;
\r
564 command_wait(command_t command)
\r
566 if(!command->execlp_errno)
\r
569 /* let this thread wait for the child so that the main thread can detect the timeout without blocking on the wait */
\r
570 int pid = waitpid(command->pid, &(command->stat_val), 0);
\r
572 if(pid != command->pid)
\r
574 error_register("waitpid() function failed", errno, command->context->command_line, command->unit->fstream->name);
\r
575 command_handle_failure(command, csr_waitpid_function_failure);
\r
579 if(WIFEXITED(command->stat_val))
\r
580 command->exit_code = WEXITSTATUS(command->stat_val);
\r
585 error_register("execlp() function failed", command->execlp_errno, command->context->command_line, command->unit->fstream->name);
\r
586 command_handle_failure(command, csr_execlp_function_failure);
\r
592 command_check(command_t command)
\r
595 cs_reason_t reason;
\r
597 /* we have a signal, store it */
\r
598 if(WIFSIGNALED(command->stat_val))
\r
600 command->signal = strdup(signal_name(WTERMSIG(command->stat_val),command->context->signal));
\r
603 /* we have a signal and not signal is expected */
\r
604 if(WIFSIGNALED(command->stat_val) && !command->context->signal)
\r
607 error_register("Command failure", EUNXPSIG, command->context->command_line, command->unit->fstream->name);
\r
608 reason = csr_unexpected_signal_caught;
\r
611 /* we have a signal that differ form the expected signal */
\r
612 if(success && WIFSIGNALED(command->stat_val) && command->context->signal && strcmp(signal_name(WTERMSIG(command->stat_val),command->context->signal),command->context->signal))
\r
615 error_register("Command failure", ESIGNOTMATCH, command->context->command_line, command->unit->fstream->name);
\r
616 reason = csr_signals_dont_match;
\r
619 /* we don't receipt the expected signal */
\r
620 if(success && !WIFSIGNALED(command->stat_val) && command->context->signal)
\r
623 error_register("Command failure", ESIGNOTRECEIPT, command->context->command_line, command->unit->fstream->name);
\r
624 reason = csr_expected_signal_not_receipt;
\r
627 /* if the command exit normaly and we expect a exit code : test it */
\r
628 if(success && WIFEXITED(command->stat_val) /* && INDEFINITE != command->context->exit_code*/)
\r
630 /* the exit codes don't match */
\r
631 if(WEXITSTATUS(command->stat_val) != command->context->exit_code)
\r
634 error_register("Command failure", EEXITCODENOTMATCH, command->context->command_line, command->unit->fstream->name);
\r
635 reason = csr_exit_codes_dont_match;
\r
639 /* if ouput handling flag is specified check the output */
\r
640 if(success && oh_check == command->context->output_handling && command->reader)
\r
642 /* make sure the reader done */
\r
643 while(!command->reader->done)
\r
644 xbt_os_thread_yield();
\r
647 CloseHandle(command->stdout_fd);
\r
649 close(command->stdout_fd);
\r
652 command->stdout_fd = INDEFINITE_FD;
\r
654 xbt_strbuff_chomp(command->output);
\r
655 xbt_strbuff_chomp(command->context->output);
\r
656 xbt_strbuff_trim(command->output);
\r
657 xbt_strbuff_trim(command->context->output);
\r
659 if(command->output->used != command->context->output->used || strcmp(command->output->data, command->context->output->data))
\r
662 error_register("Command failure", EOUTPUTNOTMATCH, command->context->command_line, command->unit->fstream->name);
\r
663 reason = csr_outputs_dont_match;
\r
669 xbt_os_mutex_acquire(command->mutex);
\r
671 if(command->status != cs_interrupted)
\r
674 /* signal the success of the command */
\r
675 command->status = cs_successeded;
\r
676 command->successeded = 1;
\r
678 /* increment the number of successeded command of the unit */
\r
679 (command->unit->successeded_cmd_nb)++;
\r
682 xbt_os_mutex_release(command->mutex);
\r
687 command_handle_failure(command,reason);
\r
693 command_kill(command_t command)
\r
695 if(INDEFINITE_PID != command->pid)
\r
696 TerminateProcess(command->pid, INDEFINITE);
\r
700 command_kill(command_t command)
\r
702 if(INDEFINITE_PID != command->pid)
\r
704 kill(command->pid,SIGTERM);
\r
706 if(!command->context->signal)
\r
707 command->context->signal = strdup("SIGTERM");
\r
709 command->exit_code = INDEFINITE;
\r
710 command->killed = 1;
\r
713 kill(command->pid,SIGKILL);
\r
721 command_interrupt(command_t command)
\r
723 xbt_os_mutex_acquire(command->mutex);
\r
725 if((command->status != cs_interrupted) && (command->status != cs_failed) && (command->status != cs_successeded))
\r
727 command->status = cs_interrupted;
\r
728 command->reason = csr_interruption_request;
\r
729 command->interrupted = 1;
\r
730 xbt_os_mutex_acquire(command->unit->mutex);
\r
731 (command->unit->interrupted_cmd_nb)++;
\r
732 xbt_os_mutex_release(command->unit->mutex);
\r
734 if(command->pid != INDEFINITE_PID)
\r
735 command_kill(command);
\r
738 xbt_os_mutex_release(command->mutex);
\r
744 command_summarize(command_t command)
\r
746 if(cs_successeded != command->status)
\r
750 if(command->killed)
\r
751 printf(" <killed command>\n");
\r
754 /* display the reason of the status of the command */
\r
755 switch(command->reason)
\r
757 /* the function pipe or CreatePipe() fails */
\r
758 case csr_pipe_function_failed :
\r
759 printf(" reason : pipe() or CreatePipe() function failed (system error)\n");
\r
762 /* reader failure reasons*/
\r
763 case csr_read_pipe_broken :
\r
764 printf(" reason : command read pipe broken\n");
\r
767 case csr_read_failure :
\r
768 printf(" reason : command stdout read failed\n");
\r
771 /* writer failure reasons */
\r
772 case csr_write_failure :
\r
773 printf(" reason : command stdin write failed\n");
\r
776 case csr_write_pipe_broken :
\r
777 printf(" reason : command write pipe broken\n");
\r
782 printf(" reason : command timeouted\n");
\r
785 /* command failure reason */
\r
786 case csr_command_not_found :
\r
787 printf(" reason : command not found\n");
\r
790 /* context failure reasons */
\r
791 case csr_exit_codes_dont_match :
\r
792 printf(" reason : exit codes don't match\n");
\r
796 /* dup2 function failure reasons */
\r
797 case csr_dup2_function_failure :
\r
798 printf(" reason : dup2() function failed\n");
\r
802 /* execlp function failure reasons */
\r
803 case csr_execlp_function_failure :
\r
804 printf(" reason : execlp() function failed\n");
\r
808 /* waitpid function failure reasons */
\r
809 case csr_waitpid_function_failure :
\r
810 printf(" reason : waitpid() function failed\n");
\r
814 /* CreateProcess function failure reasons */
\r
815 case csr_create_process_function_failure :
\r
816 printf(" reason : CreateProcesss() function failed\n");
\r
820 case csr_outputs_dont_match :
\r
823 printf(" reason : ouputs don't match\n");
\r
824 diff = xbt_str_diff(command->context->output->data,command->output->data);
\r
825 printf(" output diff :\n%s\n",diff);
\r
831 case csr_signals_dont_match :
\r
832 printf(" reason : signals don't match\n");
\r
835 case csr_unexpected_signal_caught:
\r
836 printf(" reason : unexpected signal caught\n");
\r
839 case csr_expected_signal_not_receipt :
\r
840 printf(" reason : expected signal not receipt\n");
\r
843 /* system failure reasons */
\r
844 case csr_fork_function_failure :
\r
845 printf(" reason : fork function failed\n");
\r
848 case csr_wait_failure :
\r
849 printf(" reason : wait command failure\n");
\r
852 /* global/local interruption */
\r
853 case csr_interruption_request :
\r
854 printf(" reason : the command receive a interruption request\n");
\r
859 printf(" reason : unknown \n");
\r
863 if(csr_command_not_found != command->reason && csr_fork_function_failure != command->reason && csr_execlp_function_failure != command->reason)
\r
865 if(INDEFINITE != command->exit_code)
\r
866 /* the command exit code */
\r
867 printf(" exit code : %d\n",command->exit_code);
\r
869 /* if an expected exit code was specified display it */
\r
870 if(INDEFINITE != command->context->exit_code)
\r
871 printf(" expected exit code : %d\n",command->context->exit_code);
\r
873 printf(" no expected exit code specified\n");
\r
875 /* if an expected exit code was specified display it */
\r
876 if(NULL == command->context->signal)
\r
877 printf(" no expected signal specified\n");
\r
880 if(NULL != command->signal)
\r
881 printf(" signal : %s\n",command->signal);
\r
883 printf(" expected signal : %s\n",command->context->signal);
\r
886 /* if the command has out put and the metacommand display output is specified display it */
\r
887 if(command->output && (0 != command->output->used) && (oh_display == command->context->output_handling))
\r
889 xbt_dynar_t a = xbt_str_split(command->output->data, "\n");
\r
890 char *out = xbt_str_join(a,"\n||");
\r
891 xbt_dynar_free(&a);
\r
892 printf(" output :\n||%s",out);
\r
904 command_handle_failure(command_t command, cs_reason_t reason)
\r
907 unit_t unit = command->unit;
\r
909 xbt_os_mutex_acquire(command->mutex);
\r
911 if((command->status != cs_interrupted) && (command->status != cs_failed))
\r
913 command->status = cs_failed;
\r
914 command->reason = reason;
\r
915 command->failed = 1;
\r
917 xbt_os_mutex_acquire(unit->mutex);
\r
919 /* increment the number of failed command of the unit */
\r
920 unit->failed_cmd_nb++;
\r
922 /* if the --ignore-failures option is not specified */
\r
923 if(!keep_going_unit_flag)
\r
925 if(!unit->interrupted)
\r
927 /* the unit interrupted (exit for the loop) */
\r
928 unit->interrupted = 1;
\r
930 /* release the unit */
\r
931 xbt_os_sem_release(unit->sem);
\r
934 /* if the --keep-going option is not specified */
\r
935 if(!keep_going_flag)
\r
939 /* request an global interruption by the runner */
\r
942 /* release the runner */
\r
943 xbt_os_sem_release(units_sem);
\r
948 xbt_os_mutex_release(unit->mutex);
\r
951 xbt_os_mutex_release(command->mutex);
\r
955 command_free(command_t* ptr)
\r
957 /* TODO : check the parameter */
\r
959 /* close the stdin and the stdout pipe handles */
\r
962 if((*ptr)->stdin_fd != INDEFINITE_FD)
\r
963 CloseHandle((*ptr)->stdin_fd);
\r
965 if((*ptr)->stdout_fd != INDEFINITE_FD)
\r
966 CloseHandle((*ptr)->stdout_fd);
\r
970 if((*ptr)->stdin_fd != INDEFINITE_FD)
\r
971 close((*ptr)->stdin_fd);
\r
973 if((*ptr)->stdout_fd != INDEFINITE_FD)
\r
974 close((*ptr)->stdout_fd);
\r
979 if(timer_free(&((*ptr)->timer)) < 0)
\r
986 if(writer_free(&((*ptr)->writer)) < 0)
\r
992 if(reader_free(&((*ptr)->reader)) < 0)
\r
996 xbt_strbuff_free((*ptr)->output);
\r
998 if((*ptr)->context)
\r
1000 if(context_free(&((*ptr)->context)) < 0)
\r
1004 if((*ptr)->signal)
\r
1005 free((*ptr)->signal);
\r