public inbox for frysk-cvs@sourceware.org help / color / mirror / Atom feed
From: cagney@sourceware.org To: frysk-cvs@sourceware.org Subject: [SCM] master: Prototype jni/PseudoTerminal. Date: Wed, 21 May 2008 18:41:00 -0000 [thread overview] Message-ID: <20080521184157.11243.qmail@sourceware.org> (raw) The branch, master has been updated via bca04cf8014a6ab4995b3af8abef6e2bf0d5a797 (commit) via 68963650f864c770ab27f1f8caae53f07c33c974 (commit) from ac46ba63440998b66f7038c8fe0efad8036186ff (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit bca04cf8014a6ab4995b3af8abef6e2bf0d5a797 Author: Andrew Cagney <cagney@redhat.com> Date: Wed May 21 14:40:14 2008 -0400 Prototype jni/PseudoTerminal. frysk-sys/frysk/sys/ChangeLog 2008-05-21 Andrew Cagney <cagney@redhat.com> * cni/Fork.cxx (class redirect_stdio): Fix typo out->err. * jni/PseudoTerminal.cxx: Implement. * jni/Fork.hxx: New. * jni/Fork.cxx: Merge in cni/Fork.cxx changes. commit 68963650f864c770ab27f1f8caae53f07c33c974 Author: Andrew Cagney <cagney@redhat.com> Date: Tue May 20 21:24:08 2008 -0400 Re-implement PseudoTerminal using Fork. frysk-sys/frysk/sys/ChangeLog 2008-05-20 Andrew Cagney <cagney@redhat.com> * cni/PseudoTerminal.cxx (PseudoTerminal::child): Implement. (PseudoTerminal::daemon): Implement. * cni/Fork.hxx: New. * PseudoTerminal.java (RedirectStdio): Delete. (addChild, addDaemon): Implement as natives. * cni/Fork.cxx (spawn): New. ----------------------------------------------------------------------- Summary of changes: frysk-sys/frysk/sys/ChangeLog | 12 ++ frysk-sys/frysk/sys/PseudoTerminal.java | 36 +---- frysk-sys/frysk/sys/cni/Fork.cxx | 127 +++++++--------- .../sys/{jni/PseudoTerminal.cxx => cni/Fork.hxx} | 72 +++++++--- frysk-sys/frysk/sys/cni/PseudoTerminal.cxx | 140 ++++++++++------- frysk-sys/frysk/sys/jni/Fork.cxx | 159 +++++++++----------- .../frysk/sys/jni/{PseudoTerminal.cxx => Fork.hxx} | 79 ++++++++--- frysk-sys/frysk/sys/jni/PseudoTerminal.cxx | 138 ++++++++++++++++- 8 files changed, 474 insertions(+), 289 deletions(-) copy frysk-sys/frysk/sys/{jni/PseudoTerminal.cxx => cni/Fork.hxx} (64%) copy frysk-sys/frysk/sys/jni/{PseudoTerminal.cxx => Fork.hxx} (58%) First 500 lines of diff: diff --git a/frysk-sys/frysk/sys/ChangeLog b/frysk-sys/frysk/sys/ChangeLog index c6f46b9..4a39196 100644 --- a/frysk-sys/frysk/sys/ChangeLog +++ b/frysk-sys/frysk/sys/ChangeLog @@ -1,10 +1,22 @@ 2008-05-21 Andrew Cagney <cagney@redhat.com> + * cni/Fork.cxx (class redirect_stdio): Fix typo out->err. + * jni/PseudoTerminal.cxx: Implement. + * jni/Fork.hxx: New. + * jni/Fork.cxx: Merge in cni/Fork.cxx changes. + * jni/Fork.cxx (spawn): Use elements(), not .p. * jni/Signal.cxx-sh (frysk): Ditto. 2008-05-20 Andrew Cagney <cagney@redhat.com> + * cni/PseudoTerminal.cxx (PseudoTerminal::child): Implement. + (PseudoTerminal::daemon): Implement. + * cni/Fork.hxx: New. + * PseudoTerminal.java (RedirectStdio): Delete. + (addChild, addDaemon): Implement as natives. + * cni/Fork.cxx (spawn): New. + * jni/Signal.cxx-sh: Don't leak JNI string pointers. * jni/DaemonFactory.cxx: Implement. diff --git a/frysk-sys/frysk/sys/PseudoTerminal.java b/frysk-sys/frysk/sys/PseudoTerminal.java index d53457b..8f3262d 100755 --- a/frysk-sys/frysk/sys/PseudoTerminal.java +++ b/frysk-sys/frysk/sys/PseudoTerminal.java @@ -77,51 +77,25 @@ public class PseudoTerminal extends FileDescriptor { /** * Return the path of the pseudo-terminal's slave. */ - public File getFile () - { + public File getFile() { return file; } /** - * Redirect stdin, stdout, and stderr to this PseudoTerminal. - * - * The file descriptors are created in the parent process so that - * child does not need to run the risk of running out of - * descriptors et.al. and recover from that. - */ - static private class RedirectStdio - extends Redirect - { - protected final String name; - RedirectStdio (String name) - { - this.name = name; - } - /** - * Execute in context of child. - */ - public native void reopen (); - /** - * Executed in context of parent. - */ - public void close () - { - } - } - - /** * Convenience method, adds a child process bound to this * pseudo-terminal. */ public ProcessIdentifier addChild(String[] args) { - return ChildFactory.create(new RedirectStdio (name), new Exec (args)); + return ProcessIdentifierFactory.create(child(args[0], args, name)); } + private static native int child(String exe, String[] args, String name); /** * Convenience method, adds a daemon process bound to this * pseudo-terminal. */ public ProcessIdentifier addDaemon(String[] args) { - return DaemonFactory.create(new RedirectStdio (name), new Exec (args)); + return ProcessIdentifierFactory.create(daemon(args[0], args, name)); } + private static native int daemon(String exe, String[] args, String name); } diff --git a/frysk-sys/frysk/sys/cni/Fork.cxx b/frysk-sys/frysk/sys/cni/Fork.cxx index 74db54c..d8806e2 100644 --- a/frysk-sys/frysk/sys/cni/Fork.cxx +++ b/frysk-sys/frysk/sys/cni/Fork.cxx @@ -49,38 +49,15 @@ #include "java/io/File.h" #include "frysk/sys/Fork.h" #include "frysk/sys/cni/Errno.hxx" - +#include "frysk/sys/cni/Fork.hxx" #include "frysk/sys/ProcessIdentifier.h" #include "frysk/sys/ProcessIdentifierFactory.h" -enum tracing { - DAEMON, - NO_TRACE, - PTRACE, - UTRACE, -}; - -static void -reopen(const char* file, const char* mode, FILE *stream) { - if (file == NULL) - return; - errno = 0; - ::freopen(file, mode, stream); - if (errno != 0) { - // Should not happen! - ::perror("freopen"); - ::_exit(errno); - } -} - /** - * Spawn a child, return the PID or the -ERROR. + * Spawn a child, return the PID or throw the error. */ -static int -spawn(const char* exePath, - const char* inPath, const char* outPath, const char* errPath, - int argc, char** argv, char** environ, tracing trace) { - +int +spawn(tracing trace, redirect& redirection, exec& execute) { if (trace == DAEMON) { // Do a vfork(), fork(), exec() which lets the top level process // capture the middle level fork()'s return value in a volatile. @@ -92,22 +69,24 @@ spawn(const char* exePath, case 0: // This is executed by the child with the parent blocked, the // final process id ends up in PID. - pid = ::spawn(exePath, inPath, outPath, errPath, argc, argv, 0, NO_TRACE); + pid = ::spawn(CHILD, redirection, execute); _exit (0); case -1: // This is executed after a vfork barfs. - return -errno; + throwErrno(errno, "vfork"); default: // This is executed after the child has set PID with a FORK and // then exited (which helps guarentee that the waitpid, below, // doesn't block. - if (pid < 0) - return -errno; + if (pid < 0) { + throwErrno(errno, "vfork/fork"); + } // Consume the middle players wait. int status; errno = 0; - if (waitpid (v, &status, 0) < 0) - return -errno; + if (waitpid(v, &status, 0) < 0) { + throwErrno(errno, "waitpid"); + } return pid; } } @@ -117,7 +96,7 @@ spawn(const char* exePath, pid_t pid = fork (); switch (pid) { case -1: // Fork failed. - return -errno; + throwErrno(errno, "fork"); default: // Parent return pid; case 0: // Child @@ -126,9 +105,7 @@ spawn(const char* exePath, sigfillset(&mask); ::sigprocmask(SIG_UNBLOCK, &mask, NULL); // Redirect stdio. - reopen(inPath, "r", stdin); - reopen(outPath, "w", stdout); - reopen(errPath, "w", stderr); + redirection.reopen(); switch (trace) { case PTRACE: errno = 0; @@ -141,21 +118,50 @@ spawn(const char* exePath, case UTRACE: fprintf(stderr, "\n\n>>>>> in spawn(...utrace)\n\n"); break; - case NO_TRACE: + case CHILD: break; case DAEMON: break; } - if (environ != NULL) { - ::execve(exePath, argv, environ); - } else - ::execv(exePath, argv); - // This should not happen. - ::perror("execvp"); - ::_exit (errno); + execute.execute(); + ::_exit(errno); } } +class redirect_stdio : public redirect { +private: + void reopen(const char* file, const char* mode, FILE *stream) { + if (file == NULL) + return; + errno = 0; + ::freopen(file, mode, stream); + if (errno != 0) { + // Should not happen! + ::perror("freopen"); + ::_exit(errno); + } + } + char* in; + char* out; + char* err; +public: + redirect_stdio(jstring in, jstring out, jstring err) { + this->in = MALLOC_STRING(in); + this->out = MALLOC_STRING(out); + this->err = MALLOC_STRING(err); + } + void reopen() { + reopen(in, "r", stdin); + reopen(out, "w", stdout); + reopen(err, "w", stderr); + } + ~redirect_stdio() { + JvFree(in); + JvFree(out); + JvFree(err); + } +}; + /** * Convert convert to native and then spawn. */ @@ -163,39 +169,16 @@ static int spawn(java::io::File* exe, jstring in, jstring out, jstring err, jstringArray args, jlong environ, tracing trace) { - char* exePath = MALLOC_STRING(exe->getPath()); - char* inPath = MALLOC_STRING(in); - char* outPath = MALLOC_STRING(out); - char* errPath = MALLOC_STRING(err); - int argc = args->length; - char** argv = MALLOC_ARGV(args); - int pid = ::spawn(exePath, inPath, outPath, errPath, - argc, argv, (char**)environ, trace); - JvFree(exePath); - JvFree(inPath); - JvFree(outPath); - JvFree(errPath); - JvFree(argv); - if (pid < 0) { - switch (trace) { - case NO_TRACE: - throwErrno(-pid, "fork/exec"); - case DAEMON: - throwErrno(-pid, "vfork/wait"); - case PTRACE: - throwErrno(-pid, "fork/ptrace/exec"); - case UTRACE: - throwErrno(-pid, "utrace"); - } - } - return pid; + redirect_stdio io = redirect_stdio(in, out, err); + exec_program program = exec_program(exe->getPath(), args, environ); + return ::spawn(trace, io, program); } jint frysk::sys::Fork::spawn(java::io::File* exe, jstring in, jstring out, jstring err, jstringArray args, jlong environ) { - return ::spawn(exe, in, out, err, args, environ, NO_TRACE); + return ::spawn(exe, in, out, err, args, environ, CHILD); } jint diff --git a/frysk-sys/frysk/sys/jni/PseudoTerminal.cxx b/frysk-sys/frysk/sys/cni/Fork.hxx similarity index 64% copy from frysk-sys/frysk/sys/jni/PseudoTerminal.cxx copy to frysk-sys/frysk/sys/cni/Fork.hxx index 2ae7e72..11137d8 100644 --- a/frysk-sys/frysk/sys/jni/PseudoTerminal.cxx +++ b/frysk-sys/frysk/sys/cni/Fork.hxx @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2008, Red Hat Inc. +// Copyright 2005, 2007, 2008, Red Hat Inc. // // FRYSK is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by @@ -37,24 +37,60 @@ // version and license this file solely under the GPL without // exception. -#include <stdlib.h> -#include <errno.h> +enum tracing { + CHILD, + DAEMON, + PTRACE, + UTRACE, +}; -#include "jni.hxx" +/** + * Class to redirect a child's stdio; the destructor should clean up + * the parent resources. + */ +class redirect { +public: + virtual void reopen() = 0; + virtual ~redirect() { + // where the close code goes. + } +}; -#include "jnixx/exceptions.hxx" +class exec { +public: + virtual void execute() = 0; + virtual ~exec() { + // where the close code goes. + } +}; -using namespace java::lang; +class exec_program : public exec { + char* exePath; + char** argv; + char** environ; +public: + exec_program(jstring exe, jstringArray args, jlong environ) { + this->exePath = MALLOC_STRING(exe); + this->argv = MALLOC_ARGV(args); + this->environ = (char**)(long)environ; + } + void execute() { + if (environ != NULL) { + ::execve(exePath, argv, environ); + ::perror("execve"); + } else { + ::execv(exePath, argv); + ::perror("execv"); + } + ::_exit(errno); + } + ~exec_program() { + JvFree(exePath); + JvFree(argv); + } +}; -::String -frysk::sys::PseudoTerminal::getName(::jnixx::env env, jint pty) { - const char *name = ::ptsname(pty); - if (name == NULL) - errnoException(env, errno, "ptsname"); - return String::NewStringUTF(env, name); -} - -jint -frysk::sys::PseudoTerminal::open(::jnixx::env env, bool) { - return -1; -} +/** + * Spawn a child, return the PID, or throw an error. + */ +extern int spawn(tracing trace, redirect& redirection, exec& execute); diff --git a/frysk-sys/frysk/sys/cni/PseudoTerminal.cxx b/frysk-sys/frysk/sys/cni/PseudoTerminal.cxx index 7d17563..63ec20b 100755 --- a/frysk-sys/frysk/sys/cni/PseudoTerminal.cxx +++ b/frysk-sys/frysk/sys/cni/PseudoTerminal.cxx @@ -48,13 +48,13 @@ #include <gcj/cni.h> +#include "frysk/sys/cni/Errno.hxx" +#include "frysk/sys/cni/Fork.hxx" #include "frysk/sys/PseudoTerminal.h" #include "frysk/sys/PseudoTerminal$RedirectStdio.h" -#include "frysk/sys/cni/Errno.hxx" jint -frysk::sys::PseudoTerminal::open (jboolean controllingTerminal) -{ +frysk::sys::PseudoTerminal::open(jboolean controllingTerminal) { int master; int flags = O_RDWR | (controllingTerminal ? O_NOCTTY : 0); @@ -80,73 +80,99 @@ frysk::sys::PseudoTerminal::open (jboolean controllingTerminal) } jstring -frysk::sys::PseudoTerminal::getName(jint fd) -{ +frysk::sys::PseudoTerminal::getName(jint fd) { char* pts_name = ::ptsname(fd); if (pts_name == NULL) throwErrno (errno, "ptsname"); return JvNewStringUTF (pts_name); } -void -frysk::sys::PseudoTerminal$RedirectStdio::reopen () -{ - // Detach from the existing controlling terminal. NOTE: Do not use - // tryOpen() here, this is running in a child process. - int fd = ::open ("/dev/tty", O_RDWR|O_NOCTTY); // ::open ok - if (fd >= 0) { - if (::ioctl (fd, TIOCNOTTY, NULL) < 0) - ::perror ("ioctl (/dev/tty, TIOCNOTTY)"); - ::close (fd); - - // Verify that the detach worked, this open should fail. NOTE: Do - // not use tryOpen() here, this is running in a child process. - fd = ::open ("/dev/tty", O_RDWR|O_NOCTTY); // ::open ok +class redirect_tty : public redirect { + char* pty; +public: + redirect_tty(jstring name) { + pty = MALLOC_STRING(name); + } + ~redirect_tty() { + JvFree(pty); + } + void reopen() { + // Detach from the existing controlling terminal. NOTE: Do not + // use tryOpen() here, this is running in a child process. + int fd = ::open ("/dev/tty", O_RDWR|O_NOCTTY); // ::open ok if (fd >= 0) { - ::perror ("open (re-open old controlling terminal)"); - ::exit (1); + if (::ioctl (fd, TIOCNOTTY, NULL) < 0) + ::perror ("ioctl (/dev/tty, TIOCNOTTY)"); + ::close (fd); + + // Verify that the detach worked, this open should fail. NOTE: + // Do not use tryOpen() here, this is running in a child + // process. + fd = ::open ("/dev/tty", O_RDWR|O_NOCTTY); // ::open ok + if (fd >= 0) { + ::perror ("open (re-open old controlling terminal)"); + ::exit (1); + } } - } - // Make this process the session leader. - if (::setsid () < 0) { - ::perror ("setsid"); - } + // Make this process the session leader. + if (::setsid () < 0) { + ::perror ("setsid"); + } - if (::getpgrp () != ::getpid ()) { - perror ("grp and pid differ"); - exit (1); - } + if (::getpgrp () != ::getpid ()) { + perror ("grp and pid differ"); + exit (1); + } -// // Move this to the session's process group. -// if (::setpgid (0, getpid ()) < 0) { -// perror ("setpgrp"); -// } - - // Open the new pty. - char *pty = ALLOCA_STRING (name); - int tty = open (pty, O_RDWR|O_NOCTTY); - if (tty < 0) { - perror ("open.pty"); - exit (1); - } + // // Move this to the session's process group. + // if (::setpgid (0, getpid ()) < 0) { + // perror ("setpgrp"); + // } - // Make the pty's tty the new controlling terminal. - if (::ioctl (tty, TIOCSCTTY, NULL) < 0) { - ::perror ("ioctl.TIOSCTTY"); - exit (1); hooks/post-receive -- frysk system monitor/debugger
reply other threads:[~2008-05-21 18:41 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20080521184157.11243.qmail@sourceware.org \ --to=cagney@sourceware.org \ --cc=frysk-cvs@sourceware.org \ --cc=frysk@sourceware.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: linkBe 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 read-only IMAP folder(s) and NNTP newsgroup(s).