This is the mail archive of the
frysk@sources.redhat.com
mailing list for the frysk project.
Re: Kill and refresh
On Fri, 2006-07-14 at 14:17 +0200, Mark Wielaard wrote:
> Yes, I actually have an addition to Fork which just gives you an
> Input/OutputStream to the process to communicate with. I found that a
> little more convenient then using signals. I'll post it to the list so
> you can see if that is something we might want to add.
Here it is. I found it useful to write some quick tests which needed to
exchange information with the child process without needing to attach to
the process or send signals between frysk and the child process.
2006-07-14 Mark Wielaard <mark@klomp.org>
* Fork.java (ForkedProcess): New static inner class.
(ForkedInputStream): Likewise.
(ForkedOutputStream): Likewise.
(ForkedProcess): New static method.
* cni/Fork.cxx (fork): New method.
(ForkedOutputStream::write): Likewise.
(ForkedInputStream::read(void)): Likewise.
(ForkedInputStream::read(jbyteArray,jint,jint)): Likewise.
At first I used Runtime.exec() for this, but since that spawns a new
Thread that tries to wait() on all processes that didn't work nicely
with the rest of frysk core.
Would it make sense to add this new functionality to Fork?
Cheers,
Mark
Index: frysk/sys/Fork.java
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/Fork.java,v
retrieving revision 1.3
diff -u -r1.3 Fork.java
--- frysk/sys/Fork.java 27 Sep 2005 20:00:44 -0000 1.3
+++ frysk/sys/Fork.java 14 Jul 2006 12:45:47 -0000
@@ -1,6 +1,6 @@
// This file is part of the program FRYSK.
//
-// Copyright 2005, Red Hat Inc.
+// Copyright 2005, 2006 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
@@ -39,6 +39,10 @@
package frysk.sys;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
/**
* Create a child process (using fork) that immediatly performs some
* sort of exec.
@@ -46,6 +50,67 @@
public final class Fork
{
+
+ /**
+ * Returned by the fork() method to supply the process id an
+ * InputStream and an OutputStream for communicating with the newly
+ * created process.
+ */
+ public static final class ForkedProcess
+ {
+ public final int pid;
+ public final InputStream in;
+ public final OutputStream out;
+
+ /* Package private contructor used by fork(). */
+ ForkedProcess(int pid, InputStream in, OutputStream out)
+ {
+ this.pid = pid;
+ this.in = in;
+ this.out = out;
+ }
+ }
+
+ /**
+ * Package private InputStream subclass created by fork(). Reads
+ * bytes from the stdout of the newly created process.
+ */
+ static final class ForkedInputStream extends InputStream
+ {
+ final int fd;
+
+ ForkedInputStream(int fd)
+ {
+ this.fd = fd;
+ }
+
+ public native int read() throws IOException;
+ public native int read (byte[] buf, int off, int len) throws IOException;
+ }
+
+ /**
+ * Package private OutputStream subclass created by fork(). Writes
+ * bytes to the stdin of the newly created process.
+ */
+ static final class ForkedOutputStream extends OutputStream
+ {
+ final int fd;
+
+ ForkedOutputStream(int fd)
+ {
+ this.fd = fd;
+ }
+
+ public native void write(int i) throws IOException;
+ }
+
+ /**
+ * Creates a child process running ARGV[0] with arguments. Returns
+ * the pid, InputStream and OutputStream that can be used to
+ * communicate with the process.
+ */
+ public static native ForkedProcess fork(String[] argv);
+
/**
* Create a child process running ARGV[0] with arguments
* ARGV[1..].
Index: frysk/sys/cni/Fork.cxx
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/cni/Fork.cxx,v
retrieving revision 1.3
diff -u -r1.3 Fork.cxx
--- frysk/sys/cni/Fork.cxx 9 Oct 2005 13:56:27 -0000 1.3
+++ frysk/sys/cni/Fork.cxx 14 Jul 2006 12:45:47 -0000
@@ -1,6 +1,6 @@
// This file is part of the program FRYSK.
//
-// Copyright 2005, Red Hat Inc.
+// Copyright 2005, 2006 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
@@ -48,8 +48,13 @@
#include <gcj/cni.h>
#include "frysk/sys/Fork.h"
+#include "frysk/sys/Fork$ForkedInputStream.h"
+#include "frysk/sys/Fork$ForkedOutputStream.h"
+#include "frysk/sys/Fork$ForkedProcess.h"
#include "frysk/sys/cni/Errno.hxx"
+#include <java/io/IOException.h>
+
static void
reopen (jstring file, const char *mode, FILE *stream)
{
@@ -126,6 +131,100 @@
return spawn (in, out, err, args, false);
}
+frysk::sys::Fork$ForkedProcess*
+frysk::sys::Fork::fork (jstringArray args)
+{
+ // Convert args into argv, argc.
+ int argc = JvGetArrayLength (args);
+ char **argv = (char **) alloca ((argc + 1) * sizeof (void*));
+ for (int i = 0; i < argc; i++) {
+ jstring arg = elements (args)[i];
+ int len = JvGetStringUTFLength (arg);
+ argv[i] = (char *) alloca (len + 1);
+ JvGetStringUTFRegion (arg, 0, arg->length (), argv[i]);
+ argv[i][len] = '\0';
+ }
+ argv[argc] = 0;
+
+ // Create input/output pipes.
+ int pfds[2][2];
+ errno = 0;
+ if (pipe (pfds[0]) == -1)
+ throwErrno (errno, "pipe");
+ errno = 0;
+ if (pipe (pfds[1]) == -1)
+ throwErrno (errno, "pipe");
+
+ // Fork/exec
+ errno = 0;
+ pid_t pid = ::fork ();
+ switch (pid) {
+ case -1:
+ // Fork failed.
+ throwErrno (errno, "fork");
+ case 0:
+ // Child
+ dup2 (pfds[0][0], 0);
+ close (pfds[0][1]);
+ dup2 (pfds[1][1], 1);
+ close (pfds[1][0]);
+ ::execvp (argv[0], argv);
+ // This should not happen.
+ ::perror ("execvp");
+ ::_exit (errno);
+ default:
+ frysk::sys::Fork$ForkedInputStream *in;
+ in = new frysk::sys::Fork$ForkedInputStream (pfds[1][0]);
+ close (pfds[1][1]);
+ frysk::sys::Fork$ForkedOutputStream *out;
+ out = new frysk::sys::Fork$ForkedOutputStream (pfds[0][1]);
+ close (pfds[0][0]);
+ return new frysk::sys::Fork$ForkedProcess (pid, in, out);
+ }
+}
+
+void
+frysk::sys::Fork$ForkedOutputStream::write (jint i)
+{
+ jbyte b;
+ int w;
+
+ b = (jbyte) i;
+ errno = 0;
+ w = ::write (fd, &b, 1);
+ if (w == -1)
+ throw new java::io::IOException (JvNewStringLatin1 (strerror (errno)));
+}
+
+jint
+frysk::sys::Fork$ForkedInputStream::read (void)
+{
+ jbyte b;
+ int r;
+ errno = 0;
+ r = ::read (fd, &b, 1);
+ if (r == 0)
+ return -1;
+ if (r == -1)
+ throw new java::io::IOException (JvNewStringLatin1 (strerror (errno)));
+
+ return b & 0xff;
+}
+
+jint
+frysk::sys::Fork$ForkedInputStream::read (jbyteArray buf, jint off, jint len)
+{
+ jbyte *bs = elements (buf) + off;
+ int r;
+ errno = 0;
+ r = ::read (fd, bs, len);
+ if (r == 0)
+ return -1;
+ if (r == -1)
+ throw new java::io::IOException (JvNewStringLatin1 (strerror (errno)));
+
+ return r;
+}
jint
frysk::sys::Fork::daemon (jstring in, jstring out,