if (!FD_ISSET(STDOUT_FILENO, &s->wfds))
return 0;
+ if (sot->must_set_nonblock_flag) {
+ ret = mark_fd_nonblocking(STDOUT_FILENO);
+ if (ret < 0)
+ goto out;
+ sot->must_set_nonblock_flag = false;
+ }
for (;;) {
sz = btr_next_buffer(btrn, &buf);
if (sz == 0)
btr_consume(btrn, ret);
}
out:
- if (ret < 0)
+ if (ret < 0) {
btr_remove_node(&sot->btrn);
+ /* Revert to blocking mode if necessary. */
+ fcntl(STDOUT_FILENO, F_SETFL, sot->fd_flags);
+ }
return ret;
}
/**
* \param sot The stdout task structure.
*
* This fills in the pre/post select function pointers of the task structure
- * given by \a sot and sets the stdout file descriptor to nonblocking mode.
+ * given by \a sot.
*/
void stdout_set_defaults(struct stdout_task *sot)
{
sot->task.pre_select = stdout_pre_select;
sot->task.post_select = stdout_post_select;
sprintf(sot->task.status, "stdout");
- ret = mark_fd_nonblocking(STDOUT_FILENO);
- if (ret >= 0)
- return;
- PARA_EMERG_LOG("%s\n", para_strerror(-ret));
- exit(EXIT_FAILURE);
+
+ /* See stdin.c for details. */
+ ret = fcntl(STDOUT_FILENO, F_GETFL);
+ if (ret < 0) {
+ PARA_EMERG_LOG("F_GETFL: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ sot->fd_flags = ret;
+ sot->must_set_nonblock_flag = (sot->fd_flags & O_NONBLOCK) == 0;
}