+++ /dev/null
-/*\r
- * src/reader.c - type representing a stdout reader.\r
- *\r
- * Copyright 2008,2009 Martin Quinson, Malek Cherier All right reserved. \r
- *\r
- * This program is free software; you can redistribute it and/or modify it \r
- * under the terms of the license (GNU LGPL) which comes with this package.\r
- *\r
- * Purpose:\r
- * This file contains all the definitions of the functions related with\r
- * the tesh reader type.\r
- *\r
- */ \r
- \r
-#include <unit.h>\r
-#include <reader.h>\r
-#include <command.h>\r
- \r\rXBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
-\r\r\rstatic void *\r reader_start_routine(void *p);
-\r\rreader_t \r reader_new(command_t command) \r
-{
- \rreader_t reader;
- \r\r
- /* TODO : check the parameter */ \r
- \rreader = xbt_new0(s_reader_t, 1);
- \r\rreader->thread = NULL;
- \rreader->command = command;
- \rreader->broken_pipe = 0;
- \rreader->failed = 0;
- \rreader->done = 0;
- \r\rreader->started = xbt_os_sem_init(0);
- \r\rreturn reader;
-\r}
-
-\r\rint \r reader_free(reader_t * ptr) \r
-{
- \rif ((*ptr)->started)
- \rxbt_os_sem_destroy((*ptr)->started);
- \r\rfree(*ptr);
- \r\r*ptr = NULL;
- \r\rreturn 0;
-\r}
-
-\r\rvoid \r reader_read(reader_t reader) \r
-{
- \rreader->thread = xbt_os_thread_create("", reader_start_routine, reader);
-\r} \r\r
-
-#ifdef _XBT_WIN32\r
-static void *\r reader_start_routine(void *p) \r
-{
- \rreader_t reader = (reader_t) p;
- \rcommand_t command = reader->command;
- \r\rxbt_strbuff_t output = command->output;
- \rHANDLE stdout_fd = command->stdout_fd;
- \r\rDWORD number_of_bytes_to_read = 1024; /*command->context->output->used; */
- \rDWORD number_of_bytes_readed = 0;
- \r\rchar *buffer =
- (char *) calloc(number_of_bytes_to_read + 1, sizeof(char));
- \rchar *clean =
- (char *) calloc(number_of_bytes_to_read + 1, sizeof(char));
- \rsize_t i, j;
- \r\rxbt_os_sem_release(reader->started);
- \r\rwhile (!command->failed && !command->interrupted
- && !command->successeded && !reader->failed
- && !reader->broken_pipe)
- \r {
- \rif (!ReadFile
- (stdout_fd, buffer, number_of_bytes_to_read,
- &number_of_bytes_readed, NULL) || (0 == number_of_bytes_readed))
- \r {
- \rif (GetLastError() == ERROR_BROKEN_PIPE)
- \rreader->broken_pipe = 1;
- \r
- else
- \rreader->failed = 1;
- \r\r}
- \r
- else
- \r {
- \rif (number_of_bytes_readed > 0)
- \r {
- \rfor (i = 0, j = 0; i < number_of_bytes_readed; i++)
- \rif ((buffer[i]) != '\r')
- \rclean[j++] = buffer[i];
- \r\rxbt_strbuff_append(output, clean);
- \r\rmemset(buffer, 0, 1024);
- \rmemset(clean, 0, 1024);
- \r}
- \r
- else
- \r {
- \rxbt_os_thread_yield();
- \r}
- \r}
- \r}
- \r\rfree(clean);
- \rfree(buffer);
- \r\rxbt_strbuff_chomp(command->output);
- \rxbt_strbuff_trim(command->output);
- \r\rreader->done = 1;
- \r\rif (command->failed)
- \r {
- \rif (command->reason == csr_write_failure)
- \r {
- \rif (command->output->used)
- \rINFO2("[%s] Output on write failure:\n%s", command->context->pos,
- command->output->data);
- \r
- else
- \rINFO1("[%s] No output before write failure",
- command->context->pos);
- \r}
- \r
- else if (command->reason == csr_write_pipe_broken)
- \r {
- \rif (command->output->used)
- \rINFO2("[%s] Output on broken pipe:\n%s", command->context->pos,
- command->output->data);
- \r
- else
- \rINFO1("[%s] No output before broken pipe", command->context->pos);
- \r}
- \r}
- \r
- else if (command->interrupted)
- \r {
- \rif (command->output->used)
- \rINFO2("[%s] Output on interruption:\n%s", command->context->pos,
- command->output->data);
- \r
- else
- \rINFO1("[%s] No output before interruption", command->context->pos);
- \r}
- \r
- else if (reader->failed && !command->failed && !command->interrupted
- && !command->successeded)
- \r {
- \rERROR2("[%s] Error while reading output of child `%s'",
- command->context->pos, command->context->command_line);
- \r\rif (command->output->used)
- \rINFO2("[%s] Output on read failure:\n%s", command->context->pos,
- command->output->data);
- \r
- else
- \rINFO1("[%s] No output before read failure", command->context->pos);
- \r\runit_set_error(command->unit, errno, 0, command->context->pos);
- \rcommand_kill(command);
- \rcommand_handle_failure(command, csr_read_failure);
- \r}
- \r\r\r\rreturn NULL;
-\r}
-
-\r\r
-#else /* \r */
-static void *\r reader_start_routine(void *p) \r
-{
- \rreader_t reader = (reader_t) p;
- \rcommand_t command = reader->command;
- \rxbt_strbuff_t output = command->output;
- \rint stdout_fd = command->stdout_fd;
- \rint number_of_bytes_readed;
- \rint number_of_bytes_to_read = (1024 > SSIZE_MAX) ? SSIZE_MAX : 1024;
- \r\rint total = 0;
- \r\rchar *buffer = (char *) calloc(number_of_bytes_to_read, sizeof(char));
- \rxbt_os_sem_release(reader->started);
- \r\r
- do
- \r {
- \rnumber_of_bytes_readed =
- read(stdout_fd, buffer, number_of_bytes_to_read);
- \r\rif (number_of_bytes_readed < 0 && errno != EINTR && errno != EAGAIN)
- \r {
- \rreader->failed = 1;
- \r}
- \r\rif (number_of_bytes_readed > 0)
- \r {
- \rbuffer[number_of_bytes_readed] = '\0';
- \rxbt_strbuff_append(output, buffer);
- \rtotal += total;
- \r}
- \r
- else
- \r {
- \rxbt_os_thread_yield();
- \r}
- \r\r} while (!command->failed && !command->interrupted
- && !command->successeded && !reader->failed
- && (number_of_bytes_readed !=
- 0 /* end of file <-> normal exit */ ));
- \r\rfree(buffer);
- \r\rif (close(command->stdout_fd) < 0)
- \r {
- \r
- /* TODO */ \r
- }
- \r
- else
- \rcommand->stdout_fd = INDEFINITE_FD;
- \r\rxbt_strbuff_chomp(command->output);
- \rxbt_strbuff_trim(command->output);
- \r\rreader->done = 1;
- \r\rif (command->failed)
- \r {
- \rif (command->reason == csr_write_failure)
- \r {
- \rif (command->output->used)
- \rINFO2("[%s] Output on write failure:\n%s", command->context->pos,
- command->output->data);
- \r
- else
- \rINFO1("[%s] No output before write failur",
- command->context->pos);
- \r}
- \r
- else if (command->reason == csr_write_pipe_broken)
- \r {
- \rif (command->output->used)
- \rINFO2("[%s] Output on broken pipe:\n%s", command->context->pos,
- command->output->data);
- \r
- else
- \rINFO1("[%s] No output before broken pipe", command->context->pos);
- \r}
- \r}
- \r
- else if (command->interrupted)
- \r {
- \rif (command->output->used)
- \rINFO2("[%s] Output on interruption:\n%s", command->context->pos,
- command->output->data);
- \r
- else
- \rINFO1("[%s] No output before interruption", command->context->pos);
- \r}
- \r
- else if (reader->failed && !command->failed && !command->interrupted
- && !command->successeded)
- \r {
- \rERROR2("[%s] Error while reading output of child `%s'",
- command->context->pos, command->context->command_line);
- \r\rif (command->output->used)
- \rINFO2("[%s] Output on read failure:\n%s", command->context->pos,
- command->output->data);
- \r
- else
- \rINFO1("[%s] No output before read failure", command->context->pos);
- \r\runit_set_error(command->unit, errno, 0, command->context->pos);
- \rcommand_kill(command);
- \rcommand_handle_failure(command, csr_read_failure);
- \r}
- \r\r\rreturn NULL;
-\r}
-
-\r
-#endif /* \r */
-\rvoid \r reader_wait(reader_t reader) \r
-{
- \rxbt_os_thread_join(reader->thread, NULL);
-\r} \r