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 while(!command->failed && !command->interrupted && !command->successeded && ! writer->failed && ! writer->broken_pipe && number_of_bytes_to_write)
\r
79 if(!WriteFile(writer->command->stdin_fd, input, number_of_bytes_to_write, &number_of_bytes_written, NULL))
\r
81 if(GetLastError() == ERROR_NO_DATA)
\r
82 writer->broken_pipe = 1;
\r
89 input += number_of_bytes_written;
\r
90 number_of_bytes_to_write -= number_of_bytes_written;
\r
94 command->context->input->data[0]='\0';
\r
95 command->context->input->used=0;
\r
97 if(writer->failed && !command->successeded && !command->failed && !command->interrupted)
\r
99 ERROR2("[%s] Error while writing input to child `%s'", command->context->pos, command->context->command_line);
\r
100 unit_set_error(command->unit, (int)GetLastError(), 0);
\r
101 command_handle_failure(command, csr_write_failure);
\r
103 /*else if(writer->broken_pipe && !command->successeded && !command->failed && !command->interrupted)
\r
106 ERROR2("[%s] Pipe broken while writing input to child `%s'", command->context->pos, command->context->command_line);
\r
107 unit_set_error(command->unit, (int)GetLastError(), 0);
\r
108 command_kill(command);
\r
109 command_handle_failure(command, csr_write_pipe_broken);
\r
112 CloseHandle(command->stdin_fd);
\r
113 command->stdin_fd = INDEFINITE_FD;
\r
119 writer_start_routine(void* p)
\r
121 writer_t writer = (writer_t)p;
\r
122 command_t command = writer->command;
\r
123 int number_of_bytes_to_write = command->context->input->used;
\r
124 char* input = (char*)(command->context->input->data);
\r
128 while(!command->failed && !command->interrupted && !command->successeded && number_of_bytes_to_write > 0)
\r
130 got = number_of_bytes_to_write > PIPE_BUF ? PIPE_BUF : number_of_bytes_to_write;
\r
131 got = write(writer->command->stdin_fd, input, got );
\r
138 else if(EAGAIN == errno)
\r
139 {/* the pipe is full */
\r
142 xbt_os_sem_release(writer->written);
\r
144 xbt_os_thread_yield();
\r
149 else if(EPIPE == errno)
\r
151 writer->broken_pipe = 1;
\r
156 writer->failed = 1;
\r
162 number_of_bytes_to_write -= got;
\r
166 xbt_os_thread_yield();
\r
171 xbt_os_sem_release(writer->written);
\r
174 if(close(command->stdin_fd) < 0)
\r
179 command->stdin_fd = INDEFINITE_FD;
\r
181 command->context->input->data[0]='\0';
\r
182 command->context->input->used=0;
\r
184 if(writer->failed && !command->successeded && !command->failed && !command->interrupted)
\r
186 command_kill(command);
\r
187 ERROR2("[%s] Error while writing input to child `%s'", command->context->pos, command->context->command_line);
\r
189 unit_set_error(command->unit, errno, 0);
\r
190 command_handle_failure(command, csr_write_failure);
\r
192 else if(writer->broken_pipe && !command->successeded && !command->failed && !command->interrupted)
\r
194 ERROR2("[%s] Pipe broken while writing input to child `%s'", command->context->pos, command->context->command_line);
\r
196 unit_set_error(command->unit, errno, 0);
\r
197 command_kill(command);
\r
198 command_handle_failure(command, csr_write_pipe_broken);
\r
209 writer_wait(writer_t writer)
\r
211 xbt_os_thread_join(writer->thread, NULL);
\r