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
19 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
\r
22 writer_start_routine(void* p);
\r
25 writer_new(command_t command)
\r
28 /* TODO : check the parameter */
\r
30 writer = xbt_new0(s_writer_t, 1);
\r
32 writer->thread = NULL;
\r
33 writer->command = command;
\r
34 writer->written = xbt_os_sem_init(0);
\r
35 writer->can_write = xbt_os_sem_init(0);
\r
43 writer_free(writer_t* ptr)
\r
47 xbt_os_sem_destroy((*ptr)->written);
\r
49 if((*ptr)->can_write)
\r
50 xbt_os_sem_destroy((*ptr)->can_write);
\r
60 writer_write(writer_t writer)
\r
62 writer->thread = xbt_os_thread_create("", writer_start_routine, writer);
\r
67 writer_start_routine(void* p)
\r
69 writer_t writer = (writer_t)p;
\r
70 command_t command = writer->command;
\r
72 char* input = (char*)(command->context->input->data);
\r
74 DWORD number_of_bytes_to_write = command->context->input->used;
\r
75 DWORD number_of_bytes_written = 0;
\r
77 xbt_os_sem_release(writer->written);
\r
79 while(!command->failed && !command->interrupted && !command->successeded && ! writer->failed && ! writer->broken_pipe && number_of_bytes_to_write)
\r
81 if(!WriteFile(writer->command->stdin_fd, input, number_of_bytes_to_write, &number_of_bytes_written, NULL))
\r
83 if(GetLastError() == ERROR_NO_DATA)
\r
84 writer->broken_pipe = 1;
\r
91 input += number_of_bytes_written;
\r
92 number_of_bytes_to_write -= number_of_bytes_written;
\r
96 command->context->input->data[0]='\0';
\r
97 command->context->input->used=0;
\r
99 if(writer->failed && !command->successeded && !command->failed && !command->interrupted)
\r
101 ERROR2("[%s] Error while writing input to child `%s'", command->context->pos, command->context->command_line);
\r
102 unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);
\r
103 command_handle_failure(command, csr_write_failure);
\r
105 /*else if(writer->broken_pipe && !command->successeded && !command->failed && !command->interrupted)
\r
108 ERROR2("[%s] Pipe broken while writing input to child `%s'", command->context->pos, command->context->command_line);
\r
109 unit_set_error(command->unit, (int)GetLastError(), 0);
\r
110 command_kill(command);
\r
111 command_handle_failure(command, csr_write_pipe_broken);
\r
114 CloseHandle(command->stdin_fd);
\r
115 command->stdin_fd = INDEFINITE_FD;
\r
121 writer_start_routine(void* p)
\r
123 writer_t writer = (writer_t)p;
\r
124 command_t command = writer->command;
\r
125 int number_of_bytes_to_write = command->context->input->used;
\r
126 char* input = (char*)(command->context->input->data);
\r
130 while(!command->failed && !command->interrupted && !command->successeded && number_of_bytes_to_write > 0)
\r
132 got = number_of_bytes_to_write > PIPE_BUF ? PIPE_BUF : number_of_bytes_to_write;
\r
133 got = write(writer->command->stdin_fd, input, got );
\r
140 else if(EAGAIN == errno)
\r
141 {/* the pipe is full */
\r
144 xbt_os_sem_release(writer->written);
\r
146 xbt_os_thread_yield();
\r
151 else if(EPIPE == errno)
\r
153 writer->broken_pipe = 1;
\r
158 writer->failed = 1;
\r
164 number_of_bytes_to_write -= got;
\r
168 xbt_os_thread_yield();
\r
173 xbt_os_sem_release(writer->written);
\r
176 if(close(command->stdin_fd) < 0)
\r
181 command->stdin_fd = INDEFINITE_FD;
\r
183 command->context->input->data[0]='\0';
\r
184 command->context->input->used=0;
\r
186 if(writer->failed && !command->successeded && !command->failed && !command->interrupted)
\r
188 command_kill(command);
\r
189 ERROR2("[%s] Error while writing input to child `%s'", command->context->pos, command->context->command_line);
\r
191 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
192 command_handle_failure(command, csr_write_failure);
\r
194 else if(writer->broken_pipe && !command->successeded && !command->failed && !command->interrupted)
\r
196 ERROR2("[%s] Pipe broken while writing input to child `%s'", command->context->pos, command->context->command_line);
\r
198 unit_set_error(command->unit, errno, 0, command->context->pos);
\r
199 command_kill(command);
\r
200 command_handle_failure(command, csr_write_pipe_broken);
\r
211 writer_wait(writer_t writer)
\r
213 xbt_os_thread_join(writer->thread, NULL);
\r