From: Ian Jackson <ian.jackson@eu.citrix.com>
To: xen-devel@lists.xen.org
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Subject: [PATCH 09/20] libxl: provide libxl__openpty_*
Date: Fri, 13 Apr 2012 19:40:03 +0100 [thread overview]
Message-ID: <1334342414-10289-10-git-send-email-ian.jackson@eu.citrix.com> (raw)
In-Reply-To: <1334342414-10289-1-git-send-email-ian.jackson@eu.citrix.com>
General facility for ao operations to open ptys.
This will be used by the bootloader machinery.
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
tools/libxl/libxl_aoutils.c | 127 ++++++++++++++++++++++++++++++++++++++++++
tools/libxl/libxl_internal.h | 36 ++++++++++++
2 files changed, 163 insertions(+), 0 deletions(-)
diff --git a/tools/libxl/libxl_aoutils.c b/tools/libxl/libxl_aoutils.c
index 774fa03..023de6e 100644
--- a/tools/libxl/libxl_aoutils.c
+++ b/tools/libxl/libxl_aoutils.c
@@ -186,3 +186,130 @@ int libxl__datacopier_start(libxl__datacopier_state *dc)
return rc;
}
+/*----- openpty -----*/
+
+/* implementation */
+
+static void openpty_cleanup(libxl__openpty_state *op)
+{
+ int i;
+
+ for (i=0; i<op->count; i++) {
+ libxl__openpty_result *res = &op->results[i];
+ libxl__carefd_close(res->master); res->master = 0;
+ libxl__carefd_close(res->slave); res->slave = 0;
+ }
+}
+
+static void openpty_exited(libxl__egc *egc, libxl__ev_child *child,
+ pid_t pid, int status) {
+ libxl__openpty_state *op = CONTAINER_OF(child, *op, child);
+ STATE_AO_GC(op->ao);
+
+ if (status) {
+ /* Perhaps the child gave us the fds and then exited nonzero.
+ * Well that would be odd but we don't really care. */
+ libxl_report_child_exitstatus(CTX, op->rc ? LIBXL__LOG_ERROR
+ : LIBXL__LOG_WARNING,
+ "openpty child", pid, status);
+ }
+ if (op->rc)
+ openpty_cleanup(op);
+ op->callback(egc, op);
+}
+
+int libxl__openptys(libxl__openpty_state *op,
+ const struct termios *termp,
+ const struct winsize *winp) {
+ /*
+ * This is completely crazy. openpty calls grantpt which the spec
+ * says may fork, and may not be called with a SIGCHLD handler.
+ * Now our application may have a SIGCHLD handler so that's bad.
+ * We could perhaps block it but we'd need to block it on all
+ * threads. This is just Too Hard.
+ *
+ * So instead, we run openpty in a child process. That child
+ * process then of course has only our own thread and our own
+ * signal handlers. We pass the fds back.
+ *
+ * Since our only current caller actually wants two ptys, we
+ * support calling openpty multiple times for a single fork.
+ */
+ STATE_AO_GC(op->ao);
+ int count = op->count;
+ int r, i, rc, sockets[2], ptyfds[count][2];
+ libxl__carefd *for_child = 0;
+ pid_t pid = -1;
+
+ for (i=0; i<count; i++) {
+ ptyfds[i][0] = ptyfds[i][1] = -1;
+ libxl__openpty_result *res = &op->results[i];
+ assert(!res->master);
+ assert(!res->slave);
+ }
+ sockets[0] = sockets[1] = -1; /* 0 is for us, 1 for our child */
+
+ libxl__carefd_begin();
+ r = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
+ if (r) { sockets[0] = sockets[1] = -1; }
+ for_child = libxl__carefd_opened(CTX, sockets[1]);
+ if (r) { LOGE(ERROR,"socketpair failed"); rc = ERROR_FAIL; goto out; }
+
+ pid = libxl__ev_child_fork(gc, &op->child, openpty_exited);
+ if (pid == -1) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (!pid) {
+ /* child */
+ close(sockets[0]);
+ signal(SIGCHLD, SIG_DFL);
+
+ for (i=0; i<count; i++) {
+ r = openpty(&ptyfds[i][0], &ptyfds[i][1], NULL, termp, winp);
+ if (r) { LOGE(ERROR,"openpty failed"); _exit(-1); }
+ }
+ rc = libxl__sendmsg_fds(gc, sockets[1], "",1,
+ 2*count, &ptyfds[0][0], "ptys");
+ if (rc) { LOGE(ERROR,"sendmsg to parent failed"); _exit(-1); }
+ _exit(0);
+ }
+
+ libxl__carefd_close(for_child);
+ for_child = 0;
+
+ /* this should be fast so do it synchronously */
+
+ libxl__carefd_begin();
+ char buf[1];
+ rc = libxl__recvmsg_fds(gc, sockets[0], buf,1,
+ 2*count, &ptyfds[0][0], "ptys");
+ if (!rc) {
+ for (i=0; i<count; i++) {
+ libxl__openpty_result *res = &op->results[i];
+ res->master = libxl__carefd_record(CTX, ptyfds[i][0]);
+ res->slave = libxl__carefd_record(CTX, ptyfds[i][1]);
+ }
+ }
+ /* now the pty fds are in the carefds, if they were ever open */
+ libxl__carefd_unlock();
+ if (rc)
+ goto out;
+
+ rc = 0;
+
+ out:
+ if (sockets[0] >= 0) close(sockets[0]);
+ libxl__carefd_close(for_child);
+ if (libxl__ev_child_inuse(&op->child)) {
+ op->rc = rc;
+ /* we will get a callback when the child dies */
+ return 0;
+ }
+
+ assert(rc);
+ openpty_cleanup(op);
+ return rc;
+}
+
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 20c95db..9af99ec 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1498,6 +1498,42 @@ _hidden void libxl__datacopier_kill(libxl__datacopier_state *dc);
_hidden int libxl__datacopier_start(libxl__datacopier_state *dc);
+/*----- openpty -----*/
+
+/*
+ * opens count (>0) ptys like count calls to openpty, and then
+ * calls back. On entry, all op[].master and op[].slave must be
+ * 0. On callback, either rc==0 and master and slave are non-0,
+ * or rc is a libxl error and they are both 0. If libxl__openpty
+ * returns non-0 no callback will happen and everything is left
+ * cleaned up.
+ */
+
+typedef struct libxl__openpty_state libxl__openpty_state;
+typedef struct libxl__openpty_result libxl__openpty_result;
+typedef void libxl__openpty_callback(libxl__egc *egc, libxl__openpty_state *op);
+
+struct libxl__openpty_state {
+ /* caller must fill these in, and they must all remain valid */
+ libxl__ao *ao;
+ libxl__openpty_callback *callback;
+ int count;
+ libxl__openpty_result *results; /* actual size is count, out parameter */
+ /* public, result, caller may only read in callback */
+ int rc;
+ /* private for implementation */
+ libxl__ev_child child;
+};
+
+struct libxl__openpty_result {
+ libxl__carefd *master, *slave;
+};
+
+int libxl__openptys(libxl__openpty_state *op,
+ const struct termios *termp,
+ const struct winsize *winp);
+
+
/*
* Convenience macros.
*/
--
1.7.2.5
next prev parent reply other threads:[~2012-04-13 18:40 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-04-13 18:39 [PATCH v6 00/20] libxl: subprocess handling Ian Jackson
2012-04-13 18:39 ` [PATCH 01/20] libxl: handle POLLERR, POLLHUP, POLLNVAL properly Ian Jackson
2012-04-16 7:53 ` Ian Campbell
2012-04-13 18:39 ` [PATCH 02/20] libxl: support multiple libxl__ev_fds for the same fd Ian Jackson
2012-04-16 8:04 ` Ian Campbell
2012-04-16 10:26 ` Ian Jackson
2012-04-16 11:17 ` Ian Campbell
2012-04-13 18:39 ` [PATCH 03/20] libxl: event API: new facilities for waiting for subprocesses Ian Jackson
2012-04-13 18:39 ` [PATCH 04/20] autoconf: New test for openpty et al Ian Jackson
2012-04-16 9:09 ` Ian Campbell
2012-04-16 10:32 ` Ian Jackson
2012-04-16 11:19 ` Ian Campbell
2012-04-16 11:50 ` Ian Jackson
2012-04-16 10:09 ` Roger Pau Monne
2012-04-16 10:35 ` Ian Jackson
2012-04-16 10:40 ` Roger Pau Monne
2012-04-16 10:56 ` Ian Jackson
2012-04-13 18:39 ` [PATCH 05/20] libxl: provide libxl__remove_file " Ian Jackson
2012-04-16 9:24 ` Ian Campbell
2012-04-16 10:33 ` Ian Jackson
2012-04-13 18:40 ` [PATCH 06/20] libxl: Introduce libxl__sendmsg_fds and libxl__recvmsg_fds Ian Jackson
2012-04-13 18:40 ` [PATCH 07/20] libxl: Clean up setdefault in do_domain_create Ian Jackson
2012-04-13 18:40 ` [PATCH 08/20] libxl: provide libxl__datacopier_* Ian Jackson
2012-04-13 18:40 ` Ian Jackson [this message]
2012-04-13 18:40 ` [PATCH 10/20] libxl: ao: Convert libxl_run_bootloader Ian Jackson
2012-04-13 18:40 ` [PATCH 11/20] libxl: make libxl_create_logfile const-correct Ian Jackson
2012-04-13 18:40 ` [PATCH 12/20] libxl: log bootloader output Ian Jackson
2012-04-13 18:40 ` [PATCH 13/20] libxl: Allow AO_GC and EGC_GC even if not used Ian Jackson
2012-04-16 14:43 ` Ian Campbell
2012-04-13 18:40 ` [PATCH 14/20] libxl: remove ctx->waitpid_instead Ian Jackson
2012-04-13 18:40 ` [PATCH 15/20] libxl: change some structures to unit arrays Ian Jackson
2012-04-13 18:40 ` [PATCH 16/20] libxl: ao: convert libxl__spawn_* Ian Jackson
2012-04-13 18:40 ` [PATCH 17/20] libxl: make libxl_create run bootloader via callback Ian Jackson
2012-04-13 18:40 ` [PATCH 18/20] libxl: provide progress reporting for long-running operations Ian Jackson
2012-04-13 18:40 ` [PATCH 19/20] libxl: remove malloc failure handling from NEW_EVENT Ian Jackson
2012-04-13 18:40 ` [PATCH 20/20] libxl: convert console callback to libxl_asyncprogress_how 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=1334342414-10289-10-git-send-email-ian.jackson@eu.citrix.com \
--to=ian.jackson@eu.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).