2 * src/reader.c - type representing a stdout reader.
\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 reader type.
\r
17 #include <command.h>
\r
20 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
\r
24 reader_start_routine(void* p);
\r
27 reader_new(command_t command)
\r
31 /* TODO : check the parameter */
\r
33 reader = xbt_new0(s_reader_t, 1);
\r
35 reader->thread = NULL;
\r
36 reader->command = command;
\r
37 reader->broken_pipe = 0;
\r
41 reader->started = xbt_os_sem_init(0);
\r
47 reader_free(reader_t* ptr)
\r
50 xbt_os_sem_destroy((*ptr)->started);
\r
60 reader_read(reader_t reader)
\r
62 reader->thread = xbt_os_thread_create("", reader_start_routine, reader);
\r
67 reader_start_routine(void* p)
\r
69 reader_t reader = (reader_t)p;
\r
70 command_t command = reader->command;
\r
72 xbt_strbuff_t output = command->output;
\r
73 HANDLE stdout_fd = command->stdout_fd;
\r
75 DWORD number_of_bytes_to_read = 1024; /*command->context->output->used;*/
\r
76 DWORD number_of_bytes_readed = 0;
\r
78 char* buffer = (char*)calloc(number_of_bytes_to_read + 1,sizeof(char));
\r
79 char* clean = (char*)calloc(number_of_bytes_to_read + 1,sizeof(char));
\r
82 xbt_os_sem_release(reader->started);
\r
84 while(!command->failed && !command->interrupted && !command->successeded && !reader->failed && !reader->broken_pipe)
\r
86 if(!ReadFile(stdout_fd, buffer, number_of_bytes_to_read, &number_of_bytes_readed, NULL) || (0 == number_of_bytes_readed))
\r
88 if(GetLastError() == ERROR_BROKEN_PIPE)
\r
89 reader->broken_pipe = 1;
\r
96 if(number_of_bytes_readed > 0)
\r
98 for(i= 0, j= 0; i < number_of_bytes_readed; i++)
\r
99 if((int)(buffer[i]) != 13)
\r
100 clean[j++] = buffer[i];
\r
102 xbt_strbuff_append(output,clean);
\r
104 memset(buffer, 0, 1024);
\r
105 memset(clean, 0, 1024);
\r
109 xbt_os_thread_yield();
\r
117 xbt_strbuff_chomp(command->output);
\r
118 xbt_strbuff_trim(command->output);
\r
122 if(command->failed)
\r
124 if(command->reason == csr_write_failure)
\r
126 if(command->output->used)
\r
127 INFO2("[%s] Output on write failure:\n%s",command->context->pos, command->output->data);
\r
129 INFO1("[%s] No output before write failure",command->context->pos);
\r
131 else if(command->reason == csr_write_pipe_broken)
\r
133 if(command->output->used)
\r
134 INFO2("[%s] Output on broken pipe:\n%s",command->context->pos, command->output->data);
\r
136 INFO1("[%s] No output before broken pipe",command->context->pos);
\r
139 else if(command->interrupted)
\r
141 if(command->output->used)
\r
142 INFO2("[%s] Output on interruption:\n%s",command->context->pos, command->output->data);
\r
144 INFO1("[%s] No output before interruption",command->context->pos);
\r
146 else if(reader->failed && !command->failed && !command->interrupted && !command->successeded)
\r
148 ERROR2("[%s] Error while reading output of child `%s'", command->context->pos, command->context->command_line);
\r
150 if(command->output->used)
\r
151 INFO2("[%s] Output on read failure:\n%s",command->context->pos, command->output->data);
\r
153 INFO1("[%s] No output before read failure",command->context->pos);
\r
155 unit_set_error(command->unit, errno, 0);
\r
156 command_kill(command);
\r
157 command_handle_failure(command, csr_read_failure);
\r
167 reader_start_routine(void* p)
\r
169 reader_t reader = (reader_t)p;
\r
170 command_t command = reader->command;
\r
171 xbt_strbuff_t output = command->output;
\r
172 int stdout_fd = command->stdout_fd;
\r
173 int number_of_bytes_readed;
\r
174 int number_of_bytes_to_read = (1024 > SSIZE_MAX) ? SSIZE_MAX : 1024;
\r
178 char* buffer = (char*)calloc(number_of_bytes_to_read,sizeof(char));
\r
179 xbt_os_sem_release(reader->started);
\r
183 number_of_bytes_readed = read(stdout_fd, buffer, number_of_bytes_to_read);
\r
185 if(number_of_bytes_readed < 0 && errno != EINTR && errno != EAGAIN)
\r
187 reader->failed = 1;
\r
190 if(number_of_bytes_readed > 0)
\r
192 buffer[number_of_bytes_readed]='\0';
\r
193 xbt_strbuff_append(output,buffer);
\r
198 xbt_os_thread_yield();
\r
201 }while(!command->failed && !command->interrupted && !command->successeded && !reader->failed && (number_of_bytes_readed != 0 /* end of file <-> normal exit */));
\r
205 if(close(command->stdout_fd) < 0)
\r
210 command->stdout_fd = INDEFINITE_FD;
\r
212 xbt_strbuff_chomp(command->output);
\r
213 xbt_strbuff_trim(command->output);
\r
217 if(command->failed)
\r
219 if(command->reason == csr_write_failure)
\r
221 if(command->output->used)
\r
222 INFO2("[%s] Output on write failure:\n%s",command->context->pos, command->output->data);
\r
224 INFO1("[%s] No output before write failur",command->context->pos);
\r
226 else if(command->reason == csr_write_pipe_broken)
\r
228 if(command->output->used)
\r
229 INFO2("[%s] Output on broken pipe:\n%s",command->context->pos, command->output->data);
\r
231 INFO1("[%s] No output before broken pipe",command->context->pos);
\r
234 else if(command->interrupted)
\r
236 if(command->output->used)
\r
237 INFO2("[%s] Output on interruption:\n%s",command->context->pos, command->output->data);
\r
239 INFO1("[%s] No output before interruption",command->context->pos);
\r
241 else if(reader->failed && !command->failed && !command->interrupted && !command->successeded)
\r
243 ERROR2("[%s] Error while reading output of child `%s'", command->context->pos, command->context->command_line);
\r
245 if(command->output->used)
\r
246 INFO2("[%s] Output on read failure:\n%s",command->context->pos, command->output->data);
\r
248 INFO1("[%s] No output before read failure",command->context->pos);
\r
250 unit_set_error(command->unit, errno, 0);
\r
251 command_kill(command);
\r
252 command_handle_failure(command, csr_read_failure);
\r
261 reader_wait(reader_t reader)
\r
263 xbt_os_thread_join(reader->thread, NULL);
\r