static void helper_stop(libxl__egc *egc, libxl__ao_abortable *abrt, int rc) { libxl__save_helper_state *shs = CONTAINER_OF(abrt, *shs, abrt); STATE_AO_GC(shs->ao); if (!libxl__save_helper_inuse(shs)) { helper_failed(egc, shs, rc); return; } if (!shs->rc) shs->rc = rc; libxl__kill(gc, shs->child.pid, SIGTERM, "save/restore helper"); }
static void helper_done(libxl__egc *egc, libxl__save_helper_state *shs) { STATE_AO_GC(shs->ao); libxl__ao_abortable_deregister(&shs->abrt); libxl__ev_fd_deregister(gc, &shs->readable); libxl__carefd_close(shs->pipes[0]); shs->pipes[0] = 0; libxl__carefd_close(shs->pipes[1]); shs->pipes[1] = 0; assert(!libxl__save_helper_inuse(shs)); shs->egc = egc; shs->completion_callback(egc, shs->caller_state, shs->rc, shs->retval, shs->errnoval); shs->egc = 0; }
static void helper_failed(libxl__egc *egc, libxl__save_helper_state *shs, int rc) { STATE_AO_GC(shs->ao); if (!shs->rc) shs->rc = rc; libxl__ev_fd_deregister(gc, &shs->readable); if (!libxl__save_helper_inuse(shs)) { helper_done(egc, shs); return; } libxl__kill(gc, shs->child.pid, SIGKILL, "save/restore helper"); }
static void check_all_finished(libxl__egc *egc, libxl__stream_read_state *stream, int rc) { STATE_AO_GC(stream->ao); /* * In the case of a failure, the _abort()'s below might cancel * synchronously on top of us, or asynchronously at a later point. * * We must avoid the situation where all _abort() cancel * synchronously and the completion_callback() gets called twice; * once by the first error and once by the final stacked abort(), * both of whom will find that all of the tasks have stopped. * * To avoid this problem, any stacked re-entry into this function is * ineligible to fire the completion callback. The outermost * instance will take care of completing, once the stack has * unwound. */ if (stream->sync_teardown) return; if (!stream->rc && rc) { /* First reported failure. Tear everything down. */ stream->rc = rc; stream->sync_teardown = true; libxl__stream_read_abort(egc, stream, rc); libxl__save_helper_abort(egc, &stream->shs); libxl__conversion_helper_abort(egc, &stream->chs, rc); stream->sync_teardown = false; } /* Don't fire the callback until all our parallel tasks have stopped. */ if (libxl__stream_read_inuse(stream) || libxl__save_helper_inuse(&stream->shs) || libxl__conversion_helper_inuse(&stream->chs)) return; stream->completion_callback(egc, stream, stream->rc); }