From: Ian Jackson <ian.jackson@eu.citrix.com>
To: xen-devel@lists.xen.org
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Subject: [PATCH 28/31] libxl: provide libxl__openpty_*
Date: Tue, 10 Apr 2012 20:08:02 +0100 [thread overview]
Message-ID: <1334084885-14474-29-git-send-email-ian.jackson@eu.citrix.com> (raw)
In-Reply-To: <1334084885-14474-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>
---
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 c1229e4..b33abe4 100644
--- a/tools/libxl/libxl_aoutils.c
+++ b/tools/libxl/libxl_aoutils.c
@@ -187,3 +187,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);
+
+ 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);
+ 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 8eabcfa..6850097 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1495,6 +1495,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-10 19:08 UTC|newest]
Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-04-10 19:07 [PATCH v4 00/31] libxl child process handling Ian Jackson
2012-04-10 19:07 ` [PATCH 01/31] .gitignore: Add a missing file Ian Jackson
2012-04-11 8:44 ` Ian Campbell
2012-04-10 19:07 ` [PATCH 02/31] libxl: ao: allow immediate completion Ian Jackson
2012-04-10 19:07 ` [PATCH 03/31] libxl: fix hang due to libxl__initiate_device_remove Ian Jackson
2012-04-10 19:07 ` [PATCH 04/31] libxl: Fix eventloop_iteration over-locking Ian Jackson
2012-04-10 19:07 ` [PATCH 05/31] libxl: remove poller from list in libxl__poller_get Ian Jackson
2012-04-10 19:07 ` [PATCH 06/31] libxl: Fix leak of ctx->lock Ian Jackson
2012-04-10 19:07 ` [PATCH 07/31] tools: Correct PTHREAD options in config/StdGNU.mk Ian Jackson
2012-04-10 19:07 ` [PATCH 08/31] libxl: Use PTHREAD_CFLAGS, LDFLAGS, LIBS Ian Jackson
2012-04-10 19:07 ` [PATCH 09/31] tools: Use PTHREAD_CFLAGS, _LDFLAGS, _LIBS Ian Jackson
2012-04-10 19:07 ` [PATCH 10/31] libxl: Crash (more sensibly) on malloc failure Ian Jackson
2012-04-11 9:02 ` Ian Campbell
2012-04-11 10:24 ` Ian Jackson
2012-04-11 10:47 ` Ian Campbell
2012-04-11 11:04 ` Ian Jackson
2012-04-11 11:14 ` Ian Campbell
2012-04-11 11:21 ` Ian Jackson
2012-04-11 11:23 ` Ian Jackson
2012-04-11 11:33 ` Ian Campbell
2012-04-10 19:07 ` [PATCH 11/31] libxl: Make libxl__zalloc et al tolerate a NULL gc Ian Jackson
2012-04-10 19:07 ` [PATCH 12/31] libxl: Introduce some convenience macros Ian Jackson
2012-04-10 19:07 ` [PATCH 13/31] libxl: include <ctype.h> and introduce CTYPE helper macro Ian Jackson
2012-04-10 19:07 ` [PATCH 14/31] libxl: Provide libxl_string_list_length Ian Jackson
2012-04-10 19:07 ` [PATCH 15/31] libxl: include <_libxl_paths.h> in libxl_internal.h Ian Jackson
2012-04-10 19:07 ` [PATCH 16/31] libxl: abolish libxl_ctx_postfork Ian Jackson
2012-04-10 19:07 ` [PATCH 17/31] libxl: libxl_event.c:beforepoll_internal, REQUIRE_FDS Ian Jackson
2012-04-10 19:07 ` [PATCH 18/31] libxl: Protect fds with CLOEXEC even with forking threads Ian Jackson
2012-04-11 9:14 ` Ian Campbell
2012-04-11 10:38 ` Ian Jackson
2012-04-10 19:07 ` [PATCH 19/31] libxl: provide STATE_AO_GC Ian Jackson
2012-04-11 9:17 ` Ian Campbell
2012-04-10 19:07 ` [PATCH 20/31] libxl: handle POLLERR, POLLHUP, POLLNVAL properly Ian Jackson
2012-04-11 9:21 ` Ian Campbell
2012-04-11 10:50 ` Ian Jackson
2012-04-11 10:52 ` Ian Campbell
2012-04-10 19:07 ` [PATCH 21/31] libxl: support multiple libxl__ev_fds for the same fd Ian Jackson
2012-04-10 19:07 ` [PATCH 22/31] libxl: event API: new facilities for waiting for subprocesses Ian Jackson
2012-04-11 9:42 ` Ian Campbell
2012-04-10 19:07 ` [PATCH 23/31] autoconf: New test for openpty et al Ian Jackson
2012-04-10 19:07 ` [PATCH 24/31] libxl: provide libxl__remove_file " Ian Jackson
2012-04-11 9:54 ` Ian Campbell
2012-04-11 10:56 ` Ian Jackson
2012-04-11 11:03 ` Ian Campbell
2012-04-10 19:07 ` [PATCH 25/31] libxl: Introduce libxl__sendmsg_fds and libxl__recvmsg_fds Ian Jackson
2012-04-10 19:08 ` [PATCH 26/31] libxl: Clean up setdefault in do_domain_create Ian Jackson
2012-04-11 9:57 ` Ian Campbell
2012-04-10 19:08 ` [PATCH 27/31] libxl: provide libxl__datacopier_* Ian Jackson
2012-04-11 10:47 ` Ian Campbell
2012-04-11 11:11 ` Ian Jackson
2012-04-10 19:08 ` Ian Jackson [this message]
2012-04-11 11:03 ` [PATCH 28/31] libxl: provide libxl__openpty_* Ian Campbell
2012-04-11 11:19 ` Ian Jackson
2012-04-11 11:33 ` Ian Campbell
2012-04-10 19:08 ` [PATCH 29/31] libxl: ao: Convert libxl_run_bootloader Ian Jackson
2012-04-11 11:31 ` Ian Campbell
2012-04-11 11:39 ` Ian Jackson
2012-04-11 11:45 ` Ian Campbell
2012-04-10 19:08 ` [PATCH 30/31] libxl: make libxl_create_logfile const-correct Ian Jackson
2012-04-11 9:58 ` Ian Campbell
2012-04-10 19:08 ` [PATCH 31/31] libxl: log bootloader output Ian Jackson
2012-04-11 10:00 ` Ian Campbell
2012-04-11 9:04 ` [PATCH v4 00/31] libxl child process handling Ian Campbell
2012-04-11 10:35 ` 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=1334084885-14474-29-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).