2 * src/writer.c - type representing a stdin writer.
\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 writer type.
\r
16 #include <command.h>
\r
18 \rXBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
19 \r\rstatic void *
\r writer_start_routine(void *p);
20 \r\rwriter_t
\r writer_new(command_t command)
\r
24 /* TODO : check the parameter */
\r
25 \rwriter = xbt_new0(s_writer_t, 1);
26 \r\rwriter->thread = NULL;
27 \rwriter->command = command;
28 \rwriter->written = xbt_os_sem_init(0);
29 \rwriter->can_write = xbt_os_sem_init(0);
34 \r\rint
\r writer_free(writer_t * ptr)
\r
36 \r\rif ((*ptr)->written)
37 \rxbt_os_sem_destroy((*ptr)->written);
38 \r\rif ((*ptr)->can_write)
39 \rxbt_os_sem_destroy((*ptr)->can_write);
45 \r\rvoid
\r writer_write(writer_t writer)
\r
47 \rwriter->thread = xbt_os_thread_create("", writer_start_routine, writer);
51 static void *
\r writer_start_routine(void *p)
\r
53 \rwriter_t writer = (writer_t) p;
54 \rcommand_t command = writer->command;
55 \r\rchar *input = (char *) (command->context->input->data);
56 \r\rDWORD number_of_bytes_to_write = command->context->input->used;
57 \rDWORD number_of_bytes_written = 0;
58 \r\rxbt_os_sem_release(writer->written);
59 \r\rwhile (!command->failed && !command->interrupted
60 && !command->successeded && !writer->failed
61 && !writer->broken_pipe && number_of_bytes_to_write)
64 (writer->command->stdin_fd, input, number_of_bytes_to_write,
65 &number_of_bytes_written, NULL))
67 \rif (GetLastError() == ERROR_NO_DATA)
68 \rwriter->broken_pipe = 1;
76 \rinput += number_of_bytes_written;
77 \rnumber_of_bytes_to_write -= number_of_bytes_written;
80 \r\rcommand->context->input->data[0] = '\0';
81 \rcommand->context->input->used = 0;
82 \r\rif (writer->failed && !command->successeded && !command->failed
83 && !command->interrupted)
85 \rERROR2("[%s] Error while writing input to child `%s'",
86 command->context->pos, command->context->command_line);
87 \runit_set_error(command->unit, (int) GetLastError(), 0,
88 command->context->pos);
89 \rcommand_handle_failure(command, csr_write_failure);
92 /*else if(writer->broken_pipe && !command->successeded && !command->failed && !command->interrupted)
\r
95 ERROR2("[%s] Pipe broken while writing input to child `%s'", command->context->pos, command->context->command_line);
\r
96 unit_set_error(command->unit, (int)GetLastError(), 0);
\r
97 command_kill(command);
\r
98 command_handle_failure(command, csr_write_pipe_broken);
\r
100 \rCloseHandle(command->stdin_fd);
101 \rcommand->stdin_fd = INDEFINITE_FD;
107 static void *
\r writer_start_routine(void *p)
\r
109 \rwriter_t writer = (writer_t) p;
110 \rcommand_t command = writer->command;
111 \rint number_of_bytes_to_write = command->context->input->used;
112 \rchar *input = (char *) (command->context->input->data);
115 \r\rwhile (!command->failed && !command->interrupted
116 && !command->successeded && number_of_bytes_to_write > 0)
119 number_of_bytes_to_write >
120 PIPE_BUF ? PIPE_BUF : number_of_bytes_to_write;
121 \rgot = write(writer->command->stdin_fd, input, got);
124 \rif (EINTR == errno)
127 else if (EAGAIN == errno)
128 \r { /* the pipe is full */
131 \rxbt_os_sem_release(writer->written);
133 \rxbt_os_thread_yield();
138 else if (EPIPE == errno)
140 \rwriter->broken_pipe = 1;
146 \rwriter->failed = 1;
150 \r\rnumber_of_bytes_to_write -= got;
153 \rxbt_os_thread_yield();
156 \rxbt_os_sem_release(writer->written);
157 \r\r\rif (close(command->stdin_fd) < 0)
164 \rcommand->stdin_fd = INDEFINITE_FD;
165 \r\rcommand->context->input->data[0] = '\0';
166 \rcommand->context->input->used = 0;
167 \r\rif (writer->failed && !command->successeded && !command->failed
168 && !command->interrupted)
170 \rcommand_kill(command);
171 \rERROR2("[%s] Error while writing input to child `%s'",
172 command->context->pos, command->context->command_line);
173 \r\runit_set_error(command->unit, errno, 0, command->context->pos);
174 \rcommand_handle_failure(command, csr_write_failure);
177 else if (writer->broken_pipe && !command->successeded && !command->failed
178 && !command->interrupted)
180 \rERROR2("[%s] Pipe broken while writing input to child `%s'",
181 command->context->pos, command->context->command_line);
182 \r\runit_set_error(command->unit, errno, 0, command->context->pos);
183 \rcommand_kill(command);
184 \rcommand_handle_failure(command, csr_write_pipe_broken);
186 \r\rwriter->done = 1;
192 void
\r writer_wait(writer_t writer)
\r
194 \rxbt_os_thread_join(writer->thread, NULL);