Move call of ioq_makeiov() to its use, because calling it before
empth_select() is racy, as follows.
Player thread flushes output by calling io_output(player->iop, 1).
io_output() sets up iov[] to point to queued output. empth_select()
blocks on output.
Another thread sends a C_FLASH or C_INFORM message to this player.
This calls io_output(p->iop, 0). The output file descriptor has
become writable since the player thread blocked on it, so some output
gets written and dequeued.
The player thread resumes, writes out iov[] and dequeues. Any output
already written by the other thread gets duplicated. If the other
thread's dequeue operation freed struct io buffers, there's use after
free followed by double-free.
if (iop->flags & IO_ERROR)
return -1;
- n = ioq_makeiov(iop->output, iov, IO_BUFSIZE);
-
if (wait) {
res = empth_select(iop->fd, EMPTH_FD_WRITE, NULL);
if (res == 0)
}
}
+ n = ioq_makeiov(iop->output, iov, IO_BUFSIZE);
cc = writev(iop->fd, iov, n);
if (cc < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK)