register_writer_node() is the only caller of the ->open method for paraslash
writers. It does not check its return value, which is OK for alsa, oss and osx
as these writer's ->open method always succeeds. However, the ->open() method
of the file writer may fail, for example because the output file could not be
opened. This error will be ignored and the writer node task is registered as
usual with ->fd being initialized to zero.
Fix this bug by splitting the ->open method of the file writer into the part which
merely allocates the private_file_write_data structure, hence always succeeds,
and the part which actually opens the output file. This second part is called later
from ->post_select as soon as there is data available to be written.
After this patch the ->open methods of all writers always succeed and we
may change its return value to void which is done in the next patch.
static int file_write_open(struct writer_node *wn)
{
static int file_write_open(struct writer_node *wn)
{
- struct private_file_write_data *pfwd = para_calloc(
- sizeof(struct private_file_write_data));
+ struct private_file_write_data *pfwd = para_calloc(sizeof(*pfwd));
+
+ wn->private_data = pfwd;
+ pfwd->fd = -1;
+ return 0;
+}
+
+static int prepare_output_file(struct writer_node *wn)
+{
struct file_write_args_info *conf = wn->conf;
struct file_write_args_info *conf = wn->conf;
+ struct private_file_write_data *pfwd = wn->private_data;
filename = conf->filename_arg;
else
filename = random_filename();
filename = conf->filename_arg;
else
filename = random_filename();
- wn->private_data = pfwd;
ret = para_open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
if (!conf->filename_given)
free(filename);
ret = para_open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
if (!conf->filename_given)
free(filename);
t->error = 0;
ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
t->error = 0;
ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
+ if (ret > 0 && pfwd->fd >= 0)
para_fd_set(pfwd->fd, &s->wfds, &s->max_fileno);
para_fd_set(pfwd->fd, &s->wfds, &s->max_fileno);
+ else if (ret != 0) /* error or bos and fd not yet open */
{
struct private_file_write_data *pfwd = wn->private_data;
{
struct private_file_write_data *pfwd = wn->private_data;
+ if (pfwd->fd >= 0)
+ close(pfwd->fd);
ret = btr_node_status(btrn, wn->min_iqs, BTR_NT_LEAF);
if (ret <= 0)
goto out;
ret = btr_node_status(btrn, wn->min_iqs, BTR_NT_LEAF);
if (ret <= 0)
goto out;
+ if (pfwd->fd < 0) {
+ ret = prepare_output_file(wn);
+ if (ret < 0)
+ goto out;
+ }
if (!FD_ISSET(pfwd->fd, &s->wfds))
return;
bytes = btr_next_buffer(btrn, &buf);
if (!FD_ISSET(pfwd->fd, &s->wfds))
return;
bytes = btr_next_buffer(btrn, &buf);