Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
tesh version 2
[simgrid.git] / tools / tesh2 / src / command.c
1
2 #include <command.h>
3 #include <context.h>
4 #include <writer.h>
5 #include <reader.h>
6 #include <timer.h>
7
8 #ifndef WIN32
9 #include <sys/types.h>
10 #include <sys/wait.h>
11 #endif
12
13 #include "../include/_signal.h"
14
15
16 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
17
18 static void*
19 command_start(void* p);
20
21
22 command_t
23 command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
24 {
25         command_t command = xbt_new0(s_command_t, 1);
26         
27         /* get the context of the execution of the command */
28         command->context = context_dup(context);
29         
30         /* the exit code of the command is indefinite */
31         command->exit_code = INDEFINITE;
32         
33         /* the signal of the command is indefinite */
34         command->signal = INDEFINITE_SIGNAL;
35         
36         command->failed = 0;
37         command->interrupted = 0;
38         
39         /* the mutex used to safetly access to the command unit properties */
40         command->mutex = mutex;
41         
42         if(context->output->used)
43                 /* instantiate the buffer filled with the content of the command stdout */
44                 command->output = xbt_strbuff_new();
45         else
46                 command->output = NULL;
47
48         command->pid = INDEFINITE_PID;
49         
50         command->stat_val = -1;
51         
52         /* set the unit of the command */
53         command->unit = unit; 
54         
55         /* all the commands are runned in a thread */
56         command->thread = NULL;
57         
58         command->successeded = 0;
59         
60         if(context->output->used)
61                 command->reader = reader_new(command);
62         else
63                 command->reader = NULL;
64
65         if(context->input->used)
66                 command->writer = writer_new(command);
67         else
68                 command->writer = NULL;
69
70         if(context->timeout != INDEFINITE)
71                 command->timer = timer_new(command);
72         else
73                 command->timer = NULL;
74
75         command->status = cs_initialized;
76         command->reason = csr_unknown;
77         
78         command->stdin_fd = INDEFINITE_FD;
79         command->stdout_fd = INDEFINITE_FD;
80         
81         
82         /* register the command */
83         xbt_os_mutex_acquire(mutex);
84         /*unit->commands[(unit->number_of_commands)++] = command;*/
85         vector_push_back(unit->commands, command);
86         (unit->number_of_commands)++;
87         xbt_os_mutex_release(mutex);
88         
89         #ifndef WIN32
90         command->killed = 0;
91         #endif
92
93         return command;
94 }
95
96 void
97 command_run(command_t command)
98 {
99         if(!want_silent)
100                 INFO1("tesh %s",command->context->command_line);
101         
102         if(!want_just_display)
103         {       
104                 if(!interrupted)
105                 {
106                         /* start the command */
107                         
108                         if(command->context->async)
109                         {
110                                 command->thread = xbt_os_thread_create("", command_start, command);
111                         
112                                 if(!command->thread)
113                                         ERROR0("xbt_os_thread_create() failed\n");
114                         }
115                         else
116                                 command_start(command);
117                 }
118                 else
119                 {
120                         command_interrupt(command);             
121                 }
122         }
123
124 }
125
126 static void*
127 command_start(void* p)
128 {
129         command_t command = (command_t)p;
130         unit_t unit = command->unit;
131         
132         /* the command is started */
133         command->status = cs_started;
134         
135         /* increment the number of started commands of the unit */
136         xbt_os_mutex_acquire(command->mutex);
137         (command->unit->number_of_started_commands)++;
138         xbt_os_mutex_release(command->mutex);
139         
140         /* execute the command of the test */
141         command_exec(command, command->context->command_line);
142         
143         if(cs_in_progress == command->status)
144         {
145                 /*printf("the command %p is in progress\n",command);*/
146                 
147                 /* on attend la fin de la commande.
148                  * la command peut soit se terminée normalement,
149                  * 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
150                  * soit à la suit d'une demande d'interruption
151                  */
152                 
153                 command_wait(command);
154         
155                 if(cs_failed != command->status && cs_interrupted != command->status)
156                 {
157                         /*printf("checking the command %p\n",command);*/
158                         command_check(command);
159                 }
160         }
161         
162         
163         xbt_os_mutex_acquire(command->mutex);
164         
165         /* if it's the last command release its unit */
166         if(!unit->interrupted && unit->parsed && (unit->number_of_started_commands == (unit->number_of_failed_commands + unit->number_of_interrupted_commands + unit->number_of_successeded_commands)))
167         {
168                 /* first release the mutex */
169                 unit->released = 1;
170                 xbt_os_mutex_release(command->mutex);
171                 /* the last command release the unit */
172                 xbt_os_sem_release(command->unit->sem);
173         }
174         else
175                 xbt_os_mutex_release(command->mutex);
176                 
177         
178         /* wait the end of the timer, the reader and the writer */
179         if(command->timer && command->timer->thread)
180                 timer_wait(command->timer);
181
182         if(command->writer && command->writer->thread)
183                 writer_wait(command->writer);
184
185         if(command->reader && command->reader->thread)
186                 reader_wait(command->reader);
187         
188         return NULL;
189 }
190
191 #ifdef WIN32
192 void
193 command_exec(command_t command, const char* command_line)
194 {
195         
196         STARTUPINFO si = {0};                                   /* contains the informations about the child process windows*/
197         PROCESS_INFORMATION pi = {0};                   /* contains child process informations                                          */
198         SECURITY_ATTRIBUTES sa = {0};                   /* contains the security descriptor for the pipe handles        */
199         HANDLE child_stdin_handle[2] = {NULL};  /* child_stdin_handle[1]        <-> stdout of the child process */
200         HANDLE child_stdout_handle[2] = {NULL}; /* child_stdout_handle[0]       <-> stdin of the child process  */
201         HANDLE child_stderr = NULL;
202         
203         sa.nLength = sizeof(SECURITY_ATTRIBUTES);
204     sa.lpSecurityDescriptor = NULL;                     /* use default security for the pipe handles                            */
205         
206         sa.bInheritHandle = TRUE;                               /* the pipe handles can be inherited                                            */
207         
208         if(!CreatePipe(&(child_stdin_handle[0]),&(child_stdin_handle[1]),&sa,0))
209     {
210                 ERROR1("CreatePipe1() failed (%lu)",GetLastError());
211                 command->failed = 1;
212                 command->status = cs_failed;    
213
214                 return;
215     }
216         
217         
218         if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[1]),GetCurrentProcess(),&(child_stderr),0,TRUE,DUPLICATE_SAME_ACCESS))
219     {
220                 ERROR1("DuplicateHandle1() failed (%lu)",GetLastError());
221                 
222                 CloseHandle(child_stdin_handle[0]);
223                 CloseHandle(child_stdin_handle[1]);
224
225                 command->failed = 1;
226                 command->status = cs_failed;    
227
228                 return;
229     }
230         
231         if(!CreatePipe(&(child_stdout_handle[0]),&(child_stdout_handle[1]),&sa,0))
232     {
233                 ERROR1("CreatePipe2() failed (%lu)",GetLastError()); 
234                 
235                 CloseHandle(child_stdout_handle[0]);
236                 CloseHandle(child_stdout_handle[1]);
237                 CloseHandle(child_stdin_handle[0]);
238                 CloseHandle(child_stdin_handle[1]);
239
240                 command->failed = 1;
241                 command->status = cs_failed;    
242
243                 return;
244     }
245                 
246         /* Read handle for read operations on the child std output. */
247         if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[0]),GetCurrentProcess(),&(command->stdout_fd),0,FALSE, DUPLICATE_SAME_ACCESS))
248     {
249                 CloseHandle(child_stdout_handle[0]);
250                 CloseHandle(child_stdout_handle[1]);
251                 CloseHandle(child_stdin_handle[0]);
252                 CloseHandle(child_stdin_handle[1]);
253
254                 command->failed = 1;
255                 command->status = cs_failed;    
256
257                 ERROR1("DuplicateHandle2() failed (%lu)",GetLastError()); 
258     }
259         
260         
261         /* Write handle for write operations on the child std input. */
262         if(!DuplicateHandle(GetCurrentProcess(),(child_stdout_handle[1]),GetCurrentProcess(),&(command->stdin_fd), 0,FALSE,DUPLICATE_SAME_ACCESS))
263     {
264                 CloseHandle(child_stdout_handle[0]);
265                 CloseHandle(child_stdout_handle[1]);
266                 CloseHandle(child_stdin_handle[0]);
267                 CloseHandle(child_stdin_handle[1]);
268
269                 command->failed = 1;
270                 command->status = cs_failed;    
271
272                 ERROR1("DuplicateHandle3() failed (%lu)",GetLastError());
273     }
274
275         
276         CloseHandle(child_stdin_handle[0]);
277         CloseHandle(child_stdout_handle[1]);
278         
279         if(command->timer)
280         {
281                 /* launch the timer */
282                 timer_time(command->timer);
283         }
284         
285         if(command->reader)
286         {
287                 /* launch the reader */
288                 reader_read(command->reader);
289         }
290     
291
292         if(command->writer)
293         {
294                 /* launch the writer */
295                 writer_write(command->writer);
296         }
297
298     si.cb = sizeof(STARTUPINFO);
299         
300         si.dwFlags |= STARTF_USESTDHANDLES;
301         si.hStdOutput = child_stdin_handle[1];
302         si.hStdInput  = child_stdout_handle[0];
303         si.hStdError  = child_stderr;
304
305         /* launch the process */
306         if(!CreateProcess(
307                                                 NULL,
308                                                 (char*)command_line,
309                                                 NULL,
310                                                 NULL,
311                                                 TRUE,
312                                                 CREATE_NO_WINDOW,
313                                                 NULL,
314                                                 NULL,
315                                                 &si,
316                                                 &pi)
317         )
318         {
319                 
320                 if(ERROR_FILE_NOT_FOUND == GetLastError())
321                 {
322                         exit_code = ECMDNOTFOUND;
323                         command_handle_failure(command,csr_command_not_found);
324                 }
325                 else
326                 {
327                         exit_code = EEXEC;
328                         command_handle_failure(command,csr_exec_failure);
329                 }
330     }
331         else
332         {
333                 /* the command is running */
334                 command->status = cs_in_progress;
335
336                 /* save the pid of the command */
337                 command->pid = pi.hProcess;
338
339                 /* close non used thread handle */
340                 CloseHandle(pi.hThread);
341                 
342         }
343
344         
345         /* close non used handles */
346         CloseHandle(child_stdin_handle[1]);
347     CloseHandle(child_stdout_handle[0]);
348         CloseHandle(child_stderr);
349
350
351 }
352 #else
353 void
354 command_exec(command_t command, const char* command_line)
355 {
356         int child_stdin_fd[2] ;
357         int child_stdout_fd[2];
358         
359         if(pipe(child_stdin_fd) || pipe(child_stdout_fd)) 
360         {
361                 ERROR1("pipe() failed (%d)",errno);
362                 command_handle_failure(command, csr_pipe_function_failed);      
363
364                 return;
365         }
366         
367         command->pid= fork();
368         
369         if(command->pid < 0) 
370         {
371                 close(child_stdin_fd[0]);
372                 close(child_stdin_fd[1]);
373                 close(child_stdout_fd[0]);
374                 close(child_stdout_fd[1]);
375                 
376                 exit_code = EEXEC;
377                 ERROR1("fork() failed (%d)",errno);
378                 command_handle_failure(command,csr_exec_failure);
379         }
380         else
381         {
382                 if(command->pid) 
383                 {/* father */
384                         close(child_stdin_fd[0]);
385                         close(child_stdout_fd[1]);
386                         
387                         command->stdin_fd = child_stdin_fd[1];
388                         command->stdout_fd = child_stdout_fd[0];
389
390                         if(command->reader)
391                         {
392                                 /* launch the reader */
393                                 reader_read(command->reader);
394                         }
395                     
396                         if(command->writer)
397                         {
398                                 /* launch the writer */
399                                 writer_write(command->writer);
400                         }
401                         
402                         if(command->timer)
403                         {
404                                 /* launch the timer */
405                                 timer_time(command->timer);
406                         }
407                         
408                         /* the command is running */
409                         command->status = cs_in_progress;
410                 
411                 } 
412                 else 
413                 {/* child */
414                 
415                         close(child_stdin_fd[1]);
416                         
417                         dup2(child_stdin_fd[0],0);
418                         
419                         close(child_stdin_fd[0]);
420                         
421                         close(child_stdout_fd[0]);
422                         
423                         dup2(child_stdout_fd[1],1);
424                         
425                         dup2(child_stdout_fd[1],2);
426                         
427                         close(child_stdout_fd[1]);
428                         
429                         if(command->reader)
430                                 xbt_os_sem_acquire(command->reader->started);
431                         
432                         if(command->writer)
433                                 xbt_os_sem_acquire(command->writer->started);
434                                 
435                         if(command->timer)
436                                 xbt_os_sem_acquire(command->timer->started);    
437                         
438                         execlp ("/bin/sh", "sh", "-c", command->context->command_line, NULL);
439                 }
440         }
441 }
442 #endif
443
444 #ifdef WIN32
445 void
446 command_wait(command_t command)
447 {
448         /* wait for the command terminaison */
449         DWORD rv;
450
451         if(WAIT_FAILED == WaitForSingleObject(command->pid, INFINITE))
452         {
453                 ERROR0("WaitForSingleObject() failed");
454                 /* TODO : see for the interruption      */      
455         }
456         else
457         {
458                 /* don't take care of the timer or the writer or the reader failue */
459                 if(cs_failed != command->status && cs_interrupted != command->status)
460                 {
461                         if(!GetExitCodeProcess(command->pid,&rv))
462                         {
463                                 ERROR1("GetExitCodeProcess() failed for the child %s",command->context->command_line);
464                                 /* TODO : see for the interruption      */      
465                         }
466                         else
467                                 command->stat_val = command->exit_code = rv;
468                 }
469         }
470 }
471 #else
472 void
473 command_wait(command_t command)
474 {
475         
476         int pid;
477         
478         /* let this thread wait for the child so that the main thread can detect the timeout without blocking on the wait */
479         
480         pid = waitpid(command->pid, &(command->stat_val), 0);
481         
482         /*printf("The %p command ended\n",command);*/
483         if(pid != command->pid) 
484         {
485                 ERROR1("waitpid() failed for the child %s",command->context->command_line);
486                 exit_code = EWAIT;
487                 command_handle_failure(command, csr_wait_failure);
488         }
489         else
490         {
491                 if(WIFEXITED(command->stat_val))
492                         command->exit_code = WEXITSTATUS(command->stat_val);    
493         }
494 }
495 #endif
496
497 void
498 command_check(command_t command)
499 {
500         int success = 1;
501         cs_reason_t reason;
502         
503         /* we have a signal, store it */
504         if(WIFSIGNALED(command->stat_val))
505         {
506                 command->signal = strdup(signal_name(WTERMSIG(command->stat_val),command->context->signal));
507                 INFO3("the command -PID %d %s receive the signal : %s",command->pid, command->context->command_line, command->signal);
508         }
509         
510         /* we have a signal and not signal is expected */
511         if(WIFSIGNALED(command->stat_val) && !command->context->signal) 
512         {
513                 success = 0;
514                 exit_code = EUNEXPECTEDSIG;
515                 reason = csr_unexpected_signal_caught;
516         }
517         
518         /* we have a signal that differ form the expected signal */
519         if(success && WIFSIGNALED(command->stat_val) && command->context->signal && strcmp(signal_name(WTERMSIG(command->stat_val),command->context->signal),command->context->signal)) 
520         {
521                 success = 0;
522                 exit_code = ESIGNOTMATCH;
523                 reason = csr_signals_dont_match;
524         }
525         
526         /* we don't receipt the expected signal */
527         if(success && !WIFSIGNALED(command->stat_val) && command->context->signal) 
528         {
529                 success = 0;
530                 exit_code = ESIGNOTRECEIPT;
531                 reason = csr_expected_signal_not_receipt;
532         }
533         
534         /* if the command exit normaly and we expect a exit code : test it */
535         if(success && WIFEXITED(command->stat_val) /* && INDEFINITE != command->context->exit_code*/)
536         {
537                 /* the exit codes don't match */
538                 if(WEXITSTATUS(command->stat_val) != command->context->exit_code)
539                 {
540                         success = 0;
541                         exit_code = EEXITCODENOTMATCH;
542                         reason = csr_exit_codes_dont_match;
543                 }
544         }
545         
546         /* if ouput handling flag is specified check the output */
547         if(success && oh_check == command->context->output_handling && command->reader)
548         {
549                 /* make sure the reader done */
550                 while(!command->reader->broken_pipe)
551                         xbt_os_thread_yield();
552
553                         xbt_strbuff_chomp(command->output);
554                         xbt_strbuff_chomp(command->context->output);
555                         xbt_strbuff_trim(command->output);
556                         xbt_strbuff_trim(command->context->output);
557
558                         if(command->output->used != command->context->output->used || strcmp(command->output->data, command->context->output->data))
559                         {
560                                 success = 0;
561                                 exit_code = EOUTPUTNOTMATCH;
562                                 reason = csr_outputs_dont_match;
563                         }
564         }
565         
566         if(success)
567         {
568                 xbt_os_mutex_acquire(command->mutex);
569                 
570                 if(command->status != cs_interrupted)
571                 {
572                 
573                         /* signal the success of the command */
574                         command->status = cs_successeded;
575                         command->successeded = 1;
576
577                         /* increment the number of successeded command of the unit */
578                         /*xbt_os_mutex_acquire(command->mutex);*/
579                         (command->unit->number_of_successeded_commands)++;
580                 }
581                 
582                 xbt_os_mutex_release(command->mutex);
583                         
584         }
585         else
586         {
587                 command_handle_failure(command,reason);
588         }
589 }
590
591 #ifdef WIN32
592 void
593 command_kill(command_t command)
594 {
595         if(INDEFINITE_PID != command->pid)
596                 TerminateProcess(command->pid, INDEFINITE);
597 }
598 #else
599 void
600 command_kill(command_t command)
601 {
602         if(INDEFINITE_PID != command->pid)
603         {
604                 /*INFO1("Kill the command - PID %d",command->pid);*/
605                 
606                 kill(command->pid,SIGTERM);
607                 
608                 if(!command->context->signal)
609                         command->context->signal = strdup("SIGTERM");
610                         
611                 command->exit_code = INDEFINITE;
612                 command->killed = 1;
613                 
614                 usleep(100);
615                 kill(command->pid,SIGKILL); 
616
617                 
618         }
619 }
620 #endif
621
622 void
623 command_interrupt(command_t command)
624 {
625         xbt_os_mutex_acquire(command->mutex);
626         
627         if((command->status != cs_interrupted) && (command->status != cs_failed) && (command->status != cs_successeded))
628         {
629                 /*INFO1("Begin interrupt the command - PID %d",command->pid);*/
630                 
631                 command->status = cs_interrupted;       
632                 command->reason = csr_interruption_request;
633                 command->interrupted = 1;
634                 xbt_os_mutex_acquire(command->unit->mutex);
635                 (command->unit->number_of_interrupted_commands)++;
636                 xbt_os_mutex_release(command->unit->mutex);
637                 
638                 if(command->pid != INDEFINITE_PID)
639                         command_kill(command);
640                 
641                 
642                 /*INFO1("End interrupt the command - PID %d",command->pid);*/
643         }
644         
645         xbt_os_mutex_release(command->mutex);
646         
647         
648 }
649
650 void
651 command_display_status(command_t command)
652 {
653         #ifdef WIN32
654         printf("\nCommand : PID - %p\n%s\n",command->pid,command->context->command_line);
655         #else
656         printf("\nCommand : PID - %d\n%s\n",command->pid,command->context->command_line);
657         #endif
658         printf("Status informations :\n");
659         printf("    position in the tesh file   : %s\n",command->context->line);
660         
661         /* the command successeded */
662         if(cs_successeded == command->status)
663         {
664                 /* status */
665                 printf("    status                      : success\n");
666         }
667         else
668         {
669                 
670                 /* display if the command is interrupted, failed or in a unknown status */
671                 if(cs_interrupted == command->status)
672                         printf("    status                      : interrupted\n");
673                 else if(cs_failed == command->status)
674                         printf("    status                      : failed\n");
675                 else
676                         printf("    status                      : unknown\n");
677                         
678                 #ifndef WIN32
679                 if(command->killed)
680                         printf("    <killed command>\n");
681                 #endif
682                 
683                 /* display the reason of the status of the command */
684                 switch(command->reason)
685                 {
686                         /* the function pipe or CreatePipe() fails */
687                         case csr_pipe_function_failed :
688                         printf("    reason                      : pipe() or CreatePipe() function failed (system error)\n");
689                         break;
690                         
691                         /* reader failure reasons*/
692                         case csr_read_pipe_broken :
693                         printf("    reason                      : command read pipe broken\n");
694                         break;
695
696                         case csr_read_failure :
697                         printf("    reason                      : command stdout read failed\n");
698                         break;
699         
700                         /* writer failure reasons */
701                         case csr_write_failure :
702                         printf("    reason                      : command stdin write failed\n");
703                         break;
704
705                         case csr_write_pipe_broken :
706                         printf("    reason                      : command write pipe broken\n");
707                         break;
708                         
709                         /* timer reason */
710                         case csr_timeout :
711                         printf("    reason                      : command timeouted\n");
712                         break;
713                         
714                         /* command failure reason */
715                         case csr_command_not_found :
716                         printf("    reason                      : command not found\n");
717                         break;
718                         
719                         /* context failure reasons */
720                         case csr_exit_codes_dont_match :
721                         printf("    reason                      : exit codes don't match\n");
722                         
723                         break;
724
725                         case csr_outputs_dont_match :
726                         {
727                                 char *diff;
728                                 printf("    reason                      : ouputs don't match\n");
729                                 diff = xbt_str_diff(command->context->output->data,command->output->data);              
730                                 printf("    output diff :\n%s\n",diff);
731                                 free(diff);
732                         }     
733
734                         break;
735
736                         case csr_signals_dont_match :
737                         printf("    reason                      : signals don't match\n"); 
738                         break;
739                         
740                         case csr_unexpected_signal_caught:
741                         printf("    reason                      : unexpected signal caught\n");
742                         break;
743                         
744                         case csr_expected_signal_not_receipt :
745                         printf("    reason                      : expected signal not receipt\n");
746                         break;
747
748                         /* system failure reasons */
749                         case csr_exec_failure :
750                         printf("    reason                      : can't excute the command\n");
751                         break;
752                         
753                         case csr_wait_failure :
754                         printf("    reason                      : wait command failure\n");
755                         break;
756                         
757                         /* global/local interruption */
758                         case csr_interruption_request :
759                         printf("    reason                      : the command receive a interruption request\n");
760                         break;
761                         
762                         /* unknown ? */
763                         case csr_unknown :
764                         printf("    reason                      : unknown \n");
765                 }
766         }
767
768         if(csr_command_not_found != command->reason && csr_exec_failure != command->reason)
769         {
770                 if(INDEFINITE != command->exit_code)
771                         /* the command exit code */
772                         printf("    exit code                   : %d\n",command->exit_code);
773                 
774                 /* if an expected exit code was specified display it */
775                 if(INDEFINITE != command->context->exit_code)
776                         printf("    expected exit code          : %d\n",command->context->exit_code);
777                 else
778                         printf("    no expected exit code specified\n");
779                 
780                 /* if an expected exit code was specified display it */
781                 if(NULL == command->context->signal)
782                         printf("    no expected signal specified\n");
783                 else
784                 {
785                         if(NULL != command->signal)
786                                 printf("    signal                      : %s\n",command->signal);
787                         
788                         printf("    expected signal             : %s\n",command->context->signal);
789                 }
790                 
791                 /* if the command has out put and the metacommand display output is specified display it  */
792                 if(command->output && (0 != command->output->used) && (oh_display == command->context->output_handling))
793                 {
794                         xbt_dynar_t a = xbt_str_split(command->output->data, "\n");
795                         char *out = xbt_str_join(a,"\n||");
796                         xbt_dynar_free(&a);
797                         printf("    output :\n||%s",out);
798                         free(out);
799                 }
800         }
801
802         printf("\n");
803                 
804
805 }
806
807 void
808 command_handle_failure(command_t command, cs_reason_t reason)
809 {
810         
811         unit_t unit = command->unit;
812         
813         xbt_os_mutex_acquire(command->mutex);
814
815         if((command->status != cs_interrupted) && (command->status != cs_failed))
816         {
817                 command->status = cs_failed;
818                 command->reason = reason;
819                 command->failed = 1;
820                 
821                 xbt_os_mutex_acquire(unit->mutex);
822                 
823                 /* increment the number of failed command of the unit */
824                 unit->number_of_failed_commands++;
825                 
826                 /* if the --ignore-failures option is not specified */
827                 if(!want_keep_going_unit)
828                 {
829                         if(!unit->interrupted)
830                         {
831                                 /* the unit interrupted (exit for the loop) */
832                                 unit->interrupted = 1;
833
834                                 /* release the unit */
835                                 xbt_os_sem_release(unit->sem);
836                         }
837                         
838                         /* if the --keep-going option is not specified */
839                         if(!want_keep_going)
840                         {
841                                 if(!interrupted)
842                                 {
843                                         /* request an global interruption by the runner */
844                                         interrupted = 1;
845                                         
846                                         /* release the runner */
847                                         xbt_os_sem_release(units_sem);
848                                 }
849                         }
850                 }
851
852                 xbt_os_mutex_release(unit->mutex);
853         }
854
855         xbt_os_mutex_release(command->mutex);
856 }
857
858 void
859 command_free(command_t* command)
860 {
861         /* close the stdin and the stdout pipe handles */
862
863         #ifdef WIN32
864         if((*command)->stdin_fd != INDEFINITE_FD)
865                 CloseHandle((*command)->stdin_fd);
866         if((*command)->stdout_fd != INDEFINITE_FD)
867                 CloseHandle((*command)->stdout_fd);
868         #else
869         if((*command)->stdin_fd != INDEFINITE_FD)
870                 close((*command)->stdin_fd);
871         
872         if((*command)->stdout_fd != INDEFINITE_FD)      
873                 close((*command)->stdout_fd);
874         #endif
875
876         timer_free(&((*command)->timer));
877         writer_free(&((*command)->writer));
878         reader_free(&((*command)->reader));
879         xbt_strbuff_free((*command)->output);
880         context_free(&((*command)->context));
881
882         if((*command)->signal)
883                 free((*command)->signal);
884
885         free(*command);
886         *command = NULL;
887 }
888
889
890