if (datacopier_pollhup_handled(egc, dc, revents, 0))
return;
- if (revents & ~POLLIN) {
- LOG(ERROR, "unexpected poll event 0x%x (should be POLLIN)"
+ if (revents & ~(POLLIN|POLLHUP)) {
+ LOG(ERROR,
+ "unexpected poll event 0x%x (expected POLLIN and/or POLLHUP)"
" on %s during copy of %s", revents, dc->readwhat, dc->copywhat);
datacopier_callback(egc, dc, -1, 0);
return;
}
- assert(revents & POLLIN);
+ assert(revents & (POLLIN|POLLHUP));
for (;;) {
libxl__datacopier_buf *buf = NULL;
int r;
}
if (r < 0) {
if (errno == EINTR) continue;
- if (errno == EWOULDBLOCK) break;
+ if (errno == EWOULDBLOCK) {
+ if (revents & POLLHUP) {
+ LOG(ERROR,
+ "poll reported HUP but fd read gave EWOULDBLOCK"
+ " on %s during copy of %s",
+ dc->readwhat, dc->copywhat);
+ datacopier_callback(egc, dc, -1, 0);
+ return;
+ }
+ break;
+ }
LOGE(ERROR, "error reading %s during copy of %s",
dc->readwhat, dc->copywhat);
datacopier_callback(egc, dc, 0, errno);
* errnoval!=0 means we had a read error, logged
* onwrite==-1 means some other internal failure, errnoval not valid, logged
* If we get POLLHUP, we call callback_pollhup(..., onwrite, -1);
- * or if callback_pollhup==0 this is an internal failure, as above.
+ * or if callback_pollhup==0 this is treated as eof (if POLLIN|POLLHUP
+ * on the reading fd) or an internal failure (otherwise), as above.
* In all cases copier is killed before calling this callback */
typedef void libxl__datacopier_callback(libxl__egc *egc,
libxl__datacopier_state *dc, int onwrite, int errnoval);