From: Ian Jackson <ian.jackson@eu.citrix.com>
To: xen-devel@lists.xen.org
Cc: Ian Jackson <ian.jackson@eu.citrix.com>,
Roger Pau Monne <roger.pau@citrix.com>
Subject: [PATCH 02/13] libxl: react correctly to bootloader pty master POLLHUP
Date: Thu, 2 Aug 2012 18:27:11 +0100 [thread overview]
Message-ID: <1343928442-23966-3-git-send-email-ian.jackson@eu.citrix.com> (raw)
In-Reply-To: <1343928442-23966-1-git-send-email-ian.jackson@eu.citrix.com>
Receive POLLHUP on the bootloader master pty is not an error.
Hopefully it means that the bootloader has exited and therefore the
pty slave side has no process group any more. (At least NetBSD
indicates POLLHUP on the master in this case.)
So send the bootloader SIGTERM; if it has already exited then this has
no effect (except that on some versions of NetBSD it erroneously
returns ESRCH and we print a harmless warning) and we will then
collect the bootloader's exit status and be satisfied.
However, we remember that we have done this so that if we got POLLHUP
for some other reason than that the bootloader exited we report
something resembling a useful message.
In order to implement this we need to provide a way for users of
datacopier to handle POLLHUP rather than treating it as fatal.
We rename bootloader_abort to bootloader_stop since it now no longer
only applies to error situations.
Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
-
Changes in v5:
* Correctly call dc->callback_pollhup, not dc->callback,
in datacopier_pollhup_handled.
Changes in v4:
* Track whether we sent SIGTERM due to POLLHUP so we can report
messages properly.
Changes in v3:
* datacopier provides new interface for handling POLLHUP
* Do not ignore errors on the xenconsole pty
* Rename bootloader_abort.
---
tools/libxl/libxl_aoutils.c | 23 +++++++++++++++++++++++
tools/libxl/libxl_bootloader.c | 39 +++++++++++++++++++++++++++++----------
tools/libxl/libxl_internal.h | 7 +++++--
3 files changed, 57 insertions(+), 12 deletions(-)
diff --git a/tools/libxl/libxl_aoutils.c b/tools/libxl/libxl_aoutils.c
index 99972a2..983a60a 100644
--- a/tools/libxl/libxl_aoutils.c
+++ b/tools/libxl/libxl_aoutils.c
@@ -97,11 +97,31 @@ void libxl__datacopier_prefixdata(libxl__egc *egc, libxl__datacopier_state *dc,
LIBXL_TAILQ_INSERT_TAIL(&dc->bufs, buf, entry);
}
+static int datacopier_pollhup_handled(libxl__egc *egc,
+ libxl__datacopier_state *dc,
+ short revents, int onwrite)
+{
+ STATE_AO_GC(dc->ao);
+
+ if (dc->callback_pollhup && (revents & POLLHUP)) {
+ LOG(DEBUG, "received POLLHUP on %s during copy of %s",
+ onwrite ? dc->writewhat : dc->readwhat,
+ dc->copywhat);
+ libxl__datacopier_kill(dc);
+ dc->callback_pollhup(egc, dc, onwrite, -1);
+ return 1;
+ }
+ return 0;
+}
+
static void datacopier_readable(libxl__egc *egc, libxl__ev_fd *ev,
int fd, short events, short revents) {
libxl__datacopier_state *dc = CONTAINER_OF(ev, *dc, toread);
STATE_AO_GC(dc->ao);
+ if (datacopier_pollhup_handled(egc, dc, revents, 0))
+ return;
+
if (revents & ~POLLIN) {
LOG(ERROR, "unexpected poll event 0x%x (should be POLLIN)"
" on %s during copy of %s", revents, dc->readwhat, dc->copywhat);
@@ -163,6 +183,9 @@ static void datacopier_writable(libxl__egc *egc, libxl__ev_fd *ev,
libxl__datacopier_state *dc = CONTAINER_OF(ev, *dc, towrite);
STATE_AO_GC(dc->ao);
+ if (datacopier_pollhup_handled(egc, dc, revents, 1))
+ return;
+
if (revents & ~POLLOUT) {
LOG(ERROR, "unexpected poll event 0x%x (should be POLLOUT)"
" on %s during copy of %s", revents, dc->writewhat, dc->copywhat);
diff --git a/tools/libxl/libxl_bootloader.c b/tools/libxl/libxl_bootloader.c
index ef5a91b..bfc1b56 100644
--- a/tools/libxl/libxl_bootloader.c
+++ b/tools/libxl/libxl_bootloader.c
@@ -215,6 +215,7 @@ void libxl__bootloader_init(libxl__bootloader_state *bl)
libxl__domaindeathcheck_init(&bl->deathcheck);
bl->keystrokes.ao = bl->ao; libxl__datacopier_init(&bl->keystrokes);
bl->display.ao = bl->ao; libxl__datacopier_init(&bl->display);
+ bl->got_pollhup = 0;
}
static void bootloader_cleanup(libxl__egc *egc, libxl__bootloader_state *bl)
@@ -275,7 +276,7 @@ static void bootloader_local_detached_cb(libxl__egc *egc,
}
/* might be called at any time, provided it's init'd */
-static void bootloader_abort(libxl__egc *egc,
+static void bootloader_stop(libxl__egc *egc,
libxl__bootloader_state *bl, int rc)
{
STATE_AO_GC(bl->ao);
@@ -285,8 +286,8 @@ static void bootloader_abort(libxl__egc *egc,
libxl__datacopier_kill(&bl->display);
if (libxl__ev_child_inuse(&bl->child)) {
r = kill(bl->child.pid, SIGTERM);
- if (r) LOGE(WARN, "after failure, failed to kill bootloader [%lu]",
- (unsigned long)bl->child.pid);
+ if (r) LOGE(WARN, "%sfailed to kill bootloader [%lu]",
+ rc ? "after failure, " : "", (unsigned long)bl->child.pid);
}
bl->rc = rc;
}
@@ -508,7 +509,10 @@ static void bootloader_gotptys(libxl__egc *egc, libxl__openpty_state *op)
bl->keystrokes.maxsz = BOOTLOADER_BUF_OUT;
bl->keystrokes.copywhat =
GCSPRINTF("bootloader input for domain %"PRIu32, bl->domid);
- bl->keystrokes.callback = bootloader_keystrokes_copyfail;
+ bl->keystrokes.callback = bootloader_keystrokes_copyfail;
+ bl->keystrokes.callback_pollhup = bootloader_keystrokes_copyfail;
+ /* pollhup gets called with errnoval==-1 which is not otherwise
+ * possible since errnos are nonnegative, so it's unambiguous */
rc = libxl__datacopier_start(&bl->keystrokes);
if (rc) goto out;
@@ -516,7 +520,8 @@ static void bootloader_gotptys(libxl__egc *egc, libxl__openpty_state *op)
bl->display.maxsz = BOOTLOADER_BUF_IN;
bl->display.copywhat =
GCSPRINTF("bootloader output for domain %"PRIu32, bl->domid);
- bl->display.callback = bootloader_display_copyfail;
+ bl->display.callback = bootloader_display_copyfail;
+ bl->display.callback_pollhup = bootloader_display_copyfail;
rc = libxl__datacopier_start(&bl->display);
if (rc) goto out;
@@ -562,30 +567,42 @@ static void bootloader_gotptys(libxl__egc *egc, libxl__openpty_state *op)
/* perhaps one of these will be called, but perhaps not */
static void bootloader_copyfail(libxl__egc *egc, const char *which,
- libxl__bootloader_state *bl, int onwrite, int errnoval)
+ libxl__bootloader_state *bl, int ondisplay, int onwrite, int errnoval)
{
STATE_AO_GC(bl->ao);
+ int rc = ERROR_FAIL;
+
+ if (errnoval==-1) {
+ /* POLLHUP */
+ if (!!ondisplay != !!onwrite) {
+ rc = 0;
+ bl->got_pollhup = 1;
+ } else {
+ LOG(ERROR, "unexpected POLLHUP on %s", which);
+ }
+ }
if (!onwrite && !errnoval)
LOG(ERROR, "unexpected eof copying %s", which);
- bootloader_abort(egc, bl, ERROR_FAIL);
+
+ bootloader_stop(egc, bl, rc);
}
static void bootloader_keystrokes_copyfail(libxl__egc *egc,
libxl__datacopier_state *dc, int onwrite, int errnoval)
{
libxl__bootloader_state *bl = CONTAINER_OF(dc, *bl, keystrokes);
- bootloader_copyfail(egc, "bootloader input", bl, onwrite, errnoval);
+ bootloader_copyfail(egc, "bootloader input", bl, 0, onwrite, errnoval);
}
static void bootloader_display_copyfail(libxl__egc *egc,
libxl__datacopier_state *dc, int onwrite, int errnoval)
{
libxl__bootloader_state *bl = CONTAINER_OF(dc, *bl, display);
- bootloader_copyfail(egc, "bootloader output", bl, onwrite, errnoval);
+ bootloader_copyfail(egc, "bootloader output", bl, 1, onwrite, errnoval);
}
static void bootloader_domaindeath(libxl__egc *egc, libxl__domaindeathcheck *dc)
{
libxl__bootloader_state *bl = CONTAINER_OF(dc, *bl, deathcheck);
- bootloader_abort(egc, bl, ERROR_FAIL);
+ bootloader_stop(egc, bl, ERROR_FAIL);
}
static void bootloader_finished(libxl__egc *egc, libxl__ev_child *child,
@@ -599,6 +616,8 @@ static void bootloader_finished(libxl__egc *egc, libxl__ev_child *child,
libxl__datacopier_kill(&bl->display);
if (status) {
+ if (bl->got_pollhup && WIFSIGNALED(status) && WTERMSIG(status)==SIGTERM)
+ LOG(ERROR, "got POLLHUP, sent SIGTERM");
LOG(ERROR, "bootloader failed - consult logfile %s", bl->logfile);
libxl_report_child_exitstatus(CTX, XTL_ERROR, "bootloader",
pid, status);
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 58004b3..2d6c71a 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2076,7 +2076,9 @@ typedef struct libxl__datacopier_buf libxl__datacopier_buf;
* errnoval==0 means we got eof and all data was written
* errnoval!=0 means we had a read error, logged
* onwrite==-1 means some other internal failure, errnoval not valid, logged
- * in all cases copier is killed before calling this callback */
+ * If we get POLLHUP, we call callback_pollhup(..., onwrite, -1);
+ * or if callback_pollhup==0 this is an internal failure, 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);
@@ -2095,6 +2097,7 @@ struct libxl__datacopier_state {
const char *copywhat, *readwhat, *writewhat; /* for error msgs */
FILE *log; /* gets a copy of everything */
libxl__datacopier_callback *callback;
+ libxl__datacopier_callback *callback_pollhup;
/* remaining fields are private to datacopier */
libxl__ev_fd toread, towrite;
ssize_t used;
@@ -2279,7 +2282,7 @@ struct libxl__bootloader_state {
int nargs, argsspace;
const char **args;
libxl__datacopier_state keystrokes, display;
- int rc;
+ int rc, got_pollhup;
};
_hidden void libxl__bootloader_init(libxl__bootloader_state *bl);
--
1.7.2.5
next prev parent reply other threads:[~2012-08-02 17:27 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-02 17:27 [PATCH v5 00/13] libxl: Assorted bugfixes and cleanups Ian Jackson
2012-08-02 17:27 ` [PATCH 01/13] libxl: unify libxl__device_destroy and device_hotplug_done Ian Jackson
2012-08-02 17:27 ` Ian Jackson [this message]
2012-08-03 8:32 ` [PATCH 02/13] libxl: react correctly to bootloader pty master POLLHUP Ian Campbell
2012-08-02 17:27 ` [PATCH 03/13] libxl: fix device counting race in libxl__devices_destroy Ian Jackson
2012-08-02 17:27 ` [PATCH 04/13] libxl: fix formatting of DEFINE_DEVICES_ADD Ian Jackson
2012-08-02 17:27 ` [PATCH 05/13] libxl: abolish useless `start' parameter to libxl__add_* Ian Jackson
2012-08-02 17:27 ` [PATCH 06/13] libxl: rename aodevs to multidev Ian Jackson
2012-08-02 17:27 ` [PATCH 07/13] libxl: do not blunder on if bootloader fails (again) Ian Jackson
2012-08-02 17:27 ` [PATCH 08/13] libxl: remus: mark TODOs more clearly Ian Jackson
2012-08-02 17:27 ` [PATCH 09/13] libxl: remove an unused numainfo parameter Ian Jackson
2012-08-02 17:27 ` [PATCH 10/13] libxl: idl: always initialise KeyedEnum keyvar in member init Ian Jackson
2012-08-02 17:27 ` [PATCH 11/13] libxl: correct some comments regarding event API and fds Ian Jackson
2012-08-03 8:35 ` Ian Campbell
2012-08-03 10:53 ` Ian Jackson
2012-08-02 17:27 ` [PATCH 12/13] libxl: add a comment re the memory management API instability Ian Jackson
2012-08-03 8:35 ` Ian Campbell
2012-08-02 17:27 ` [PATCH 13/13] libxl: -Wunused-parameter Ian Jackson
2012-08-03 8:08 ` Ian Campbell
2012-08-03 8:59 ` [PATCH v5 00/13] libxl: Assorted bugfixes and cleanups Ian Campbell
2012-08-03 11:05 ` Ian Jackson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1343928442-23966-3-git-send-email-ian.jackson@eu.citrix.com \
--to=ian.jackson@eu.citrix.com \
--cc=roger.pau@citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).