[RFC] osprocess: Introduce a simple sub-process package

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[RFC] osprocess: Introduce a simple sub-process package

Holger Freyther
From: Holger Hans Peter Freyther <[hidden email]>

The >>#popen: code does not return the pid which makes shutting down
the forked process quite difficult. Introduce a sub-process package
that can be used to fork, kill and read from the stdout/stdin.

This package should be more deeply integrated with the sysdep layer,
e.g. it assumes that SIGCHLD, SIGFPE is handled by sysdep (e.g. a
popen was previously used). It would be nice if one could have a Sempahore
for the SIGCHLD like one has with the fileOp: operations.
---
 ChangeLog                            |    4 +
 configure.ac                         |    1 +
 packages/osprocess/ChangeLog         |    6 ++
 packages/osprocess/Makefile.am       |   10 +++
 packages/osprocess/Makefile.frag     |    5 ++
 packages/osprocess/OSProcess.st      |  151 ++++++++++++++++++++++++++++++++++
 packages/osprocess/OSProcessTests.st |    7 ++
 packages/osprocess/gst_osprocess.c   |  150 +++++++++++++++++++++++++++++++++
 packages/osprocess/package.xml       |   14 ++++
 9 files changed, 348 insertions(+)
 create mode 100644 packages/osprocess/ChangeLog
 create mode 100644 packages/osprocess/Makefile.am
 create mode 100644 packages/osprocess/Makefile.frag
 create mode 100644 packages/osprocess/OSProcess.st
 create mode 100644 packages/osprocess/OSProcessTests.st
 create mode 100644 packages/osprocess/gst_osprocess.c
 create mode 100644 packages/osprocess/package.xml

diff --git a/ChangeLog b/ChangeLog
index d1d5792..2cfcb5a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2012-12-28  Holger Freyther  <[hidden email]>
+
+ * configure.ac: Add a OSProcess package.
+
 2012-10-09  Paolo Bonzini  <[hidden email]>
             Holger Freyther  <[hidden email]>
 
diff --git a/configure.ac b/configure.ac
index 05a7c82..ed35f62 100644
--- a/configure.ac
+++ b/configure.ac
@@ -574,6 +574,7 @@ GST_PACKAGE_ENABLE([Compiler], [stinst/compiler])
 GST_PACKAGE_ENABLE([Parser], [stinst/parser])
 GST_PACKAGE_ENABLE([ClassPublisher], [stinst/doc])
 GST_PACKAGE_ENABLE([ProfileTools], [profile])
+GST_PACKAGE_ENABLE([OSProcess], [osprocess], [], [], [Makefile], [gst-osprocess.la])
 GST_PACKAGE_ENABLE([ROE], [roe])
 GST_PACKAGE_ENABLE([SandstoneDb], [sandstonedb])
 GST_PACKAGE_ENABLE([Seaside-Core], [seaside/core])
diff --git a/packages/osprocess/ChangeLog b/packages/osprocess/ChangeLog
new file mode 100644
index 0000000..ce36962
--- /dev/null
+++ b/packages/osprocess/ChangeLog
@@ -0,0 +1,6 @@
+2012-12-27  Holger Hans Peter Freyther  <[hidden email]>
+
+ * Makefile.am: Add.
+ * package.xml: Likewise.
+ * OSProcess.st: Likewise.
+ * gst_osprocess.c: Likewise.
diff --git a/packages/osprocess/Makefile.am b/packages/osprocess/Makefile.am
new file mode 100644
index 0000000..dfd78ce
--- /dev/null
+++ b/packages/osprocess/Makefile.am
@@ -0,0 +1,10 @@
+moduleexec_LTLIBRARIES = gst-osprocess.la
+
+AM_CPPFLAGS = -I$(top_srcdir)/libgst -I$(top_srcdir)/lib-src
+
+gst_module_ldflags = -rpath $(moduleexecdir) -release $(VERSION) -module \
+        -no-undefined -export-symbols-regex gst_initModule
+
+gst_osprocess_la_SOURCES = gst_osprocess.c
+gst_osprocess_la_LDFLAGS = $(gst_module_ldflags)
+
diff --git a/packages/osprocess/Makefile.frag b/packages/osprocess/Makefile.frag
new file mode 100644
index 0000000..94a75cf
--- /dev/null
+++ b/packages/osprocess/Makefile.frag
@@ -0,0 +1,5 @@
+OSProcess_FILES = \
+packages/osprocess/OSProcess.st packages/osprocess/ChangeLog packages/osprocess/OSProcessTests.st
+$(OSProcess_FILES):
+$(srcdir)/packages/osprocess/stamp-classes: $(OSProcess_FILES)
+ touch $(srcdir)/packages/osprocess/stamp-classes
diff --git a/packages/osprocess/OSProcess.st b/packages/osprocess/OSProcess.st
new file mode 100644
index 0000000..31b7658
--- /dev/null
+++ b/packages/osprocess/OSProcess.st
@@ -0,0 +1,151 @@
+"=====================================================================
+|
+|   External OSProcess handling
+|
+|
+ ======================================================================"
+
+"======================================================================
+|
+| Copyright 2012 Free Software Foundation, Inc.
+| Written by Holger Hans Peter Freyther
+| baesed on work by Gwenael Casaccio
+|
+| This file is part of the GNU Smalltalk class library.
+|
+| The GNU Smalltalk class library is free software; you can redistribute it
+| and/or modify it under the terms of the GNU Lesser General Public License
+| as published by the Free Software Foundation; either version 2.1, or (at
+| your option) any later version.
+|
+| The GNU Smalltalk class library is distributed in the hope that it will be
+| useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+| General Public License for more details.
+|
+| You should have received a copy of the GNU Lesser General Public License
+| along with the GNU Smalltalk class library; see the file COPYING.LIB.
+| If not, write to the Free Software Foundation, 59 Temple Place - Suite
+| 330, Boston, MA 02110-1301, USA.  
+|
+ ======================================================================"
+
+Object subclass: OSProcess [
+    | pid stdin stdout |
+    <category: 'OSProcess'>
+
+    OSProcess class >> fileDescriptorFamily [
+ <category: 'stream-family'>
+ ^ FileStream
+    ]
+
+    OSProcess class >> SIGINT [
+ <category: 'signals'>
+ ^ 2
+    ]
+
+    OSProcess class >> SIGKILL [
+ <category: 'signals'>
+ ^ 9
+    ]
+
+    OSProcess class >> kill: pid signal: asig [
+ <category: 'syscall'>
+ <cCall: 'kill' returning: #long args: #(#long #int)>
+    ]
+
+    OSProcess class >> waitpid: pid status: anIntPtr options: anInteger [
+ <category: 'syscall'>
+ <cCall: 'waitpid' returning: #long args: #(#long (#ptr #int) #int)>
+    ]
+
+    OSProcess class >> getpid [
+ <category: 'syscall'>
+ <cCall: 'getpid' returning: #long args: #()>
+    ]
+
+    OSProcess class >> getppid [
+ <category: 'syscall'>
+ <cCall: 'getppid' returning: #long args: #()>
+    ]
+
+    OSProcess class >> internalFork: command args: args stdin: outIn stdout: outOut [
+ <cCall: 'gst_osprocess_fork_and_exec' returning: #int args: #(#self #string (#ptr #string) #smalltalk #smalltalk #smalltalk)>
+    ]
+
+    OSProcess class >> forkAndExec: command args: args [
+ | argv i res pid in out|
+ <category: 'exec'>
+
+ "From ThisOSOSProcess. Make sure the last item is null terminated"
+ argv := (CStringType arrayType: args size + 2) gcNew.
+ argv at: 0 put: command.
+
+ "Add all arguments"
+ i := 1.
+ args do: [:arg |
+    argv at: i put: arg.
+    i := i + 1].
+
+ "Null terminate.. once more"
+ argv at: i put: nil.
+
+ "Fork now and get things out of the call."
+ in := self fileDescriptorFamily new.
+ out := self fileDescriptorFamily new.
+ pid := self internalFork: command args: argv
+    stdin: in stdout: out.
+ pid < 0
+    ifTrue: [^self error: 'Failed to fork the process'].
+
+ "Initialize the sockets, the fds were set inside the fork"
+ in initialize.
+ out initialize.
+
+ ^ OSProcess new
+    stdin: in;
+    stdout: out;
+    pid: pid;
+    yourself.
+    ]
+
+    stdin: aStd [
+ <category: 'creation'>
+ stdin := aStd.
+    ]
+
+    stdout: aStd [
+ <category: 'creation'>
+ stdout := aStd.
+    ]
+
+    pid: aPid [
+ <category: 'creation'>
+ pid := aPid.
+    ]
+
+    stdin [
+ <category: 'stream'>
+ ^ stdin
+    ]
+
+    stdout [
+ <category: 'stream'>
+ ^ stdout
+    ]
+
+    kill [
+ <category: 'termination'>
+ ^ self sendSignal: self class SIGKILL.
+    ]
+
+    sendSignal: aSig [
+ <category: 'termination'>
+ ^ self class kill: pid signal: aSig.
+    ]
+
+    close [
+ stdin close.
+ stdout close.
+    ]
+]
diff --git a/packages/osprocess/OSProcessTests.st b/packages/osprocess/OSProcessTests.st
new file mode 100644
index 0000000..d858552
--- /dev/null
+++ b/packages/osprocess/OSProcessTests.st
@@ -0,0 +1,7 @@
+Eval [
+PackageLoader fileInPackage: #OSProcess.
+[
+ (OSProcess.OSProcess forkAndExec: 'ls' args: #('/')) inspect; close.
+ stdin next.
+] repeat.
+]
diff --git a/packages/osprocess/gst_osprocess.c b/packages/osprocess/gst_osprocess.c
new file mode 100644
index 0000000..17b2e2e
--- /dev/null
+++ b/packages/osprocess/gst_osprocess.c
@@ -0,0 +1,150 @@
+/******************************* -*- C -*- ****************************
+ *
+ *      Subprocess handling
+ *
+ *
+ ***********************************************************************/
+/***********************************************************************
+ *
+ * Copyright 2012 Free Software Foundation, Inc.
+ * Written by Holger Hans Peter Freyther.
+ *
+ * Forking code from libgst/sysdep/posix/files.c:
+ * Copyright 1988,89,90,91,92,94,95,99,2000,2001,2002,2003,2006,2007,2008,2009
+ *
+ * This file is part of GNU Smalltalk.
+ *
+ * GNU Smalltalk is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * Linking GNU Smalltalk statically or dynamically with other modules is
+ * making a combined work based on GNU Smalltalk.  Thus, the terms and
+ * conditions of the GNU General Public License cover the whole
+ * combination.
+ *
+ * In addition, as a special exception, the Free Software Foundation
+ * give you permission to combine GNU Smalltalk with free software
+ * programs or libraries that are released under the GNU LGPL and with
+ * independent programs running under the GNU Smalltalk virtual machine.
+ *
+ * You may copy and distribute such a system following the terms of the
+ * GNU GPL for GNU Smalltalk and the licenses of the other code
+ * concerned, provided that you include the source code of that other
+ * code when and as the GNU GPL requires distribution of source code.
+ *
+ * Note that people who make modified versions of GNU Smalltalk are not
+ * obligated to grant this special exception for their modified
+ * versions; it is their choice whether to do so.  The GNU General
+ * Public License gives permission to release a modified version without
+ * this exception; this exception also makes it possible to release a
+ * modified version which carries forward this exception.
+ *
+ * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ ***********************************************************************/
+
+#include "gstpub.h"
+
+#include <sys/types.h>          /* See NOTES */
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+static VMProxy *vmProxy;
+
+typedef struct st_OSProcess {
+  OBJ_HEADER;
+  OOP pid;
+  OOP _stdin;
+  OOP _stdout;
+} *OSProcess;
+
+static pid_t
+gst_fork_and_exec (OOP self, const char *cmd, char * const argv[], OOP in, OOP out)
+{
+  /*
+   * TODO: the SIGCHLD handler needs to be installed by gst before
+   * the whole code should move into the sysdeps so we can get notifications
+   * for the waitpid result.
+   * The forking code is taken from sysdep/posix/files.c
+   */
+
+  int stdin_pipe[2];
+  int stdout_pipe[2];
+
+  int result;
+
+  result = socketpair (AF_UNIX, SOCK_STREAM, 0, stdin_pipe);
+  if (result == -1)
+    return -1;
+  result = socketpair (AF_UNIX, SOCK_STREAM, 0, stdout_pipe);
+  if (result == -1) {
+    close(stdin_pipe[0]);
+    close(stdin_pipe[1]);
+    return -1;
+  }
+
+  /* TODO: create a pipe with close on exec to check if the process runs? */
+
+  /* We suppose it is a system that has fork.  */
+  result = fork ();
+  if (result == 0)
+    {
+      /* Child process */
+      close (stdin_pipe[0]);
+      close (stdout_pipe[0]);
+
+      /* Setup file descriptor */
+      dup2 (stdin_pipe[1], STDIN_FILENO);
+      dup2 (stdout_pipe[1], STDOUT_FILENO);
+      close (stdin_pipe[1]);
+      close (stdout_pipe[1]);
+
+      /* stderr is still going to the main stream */
+      /* close other fds? */
+
+      execvp(cmd, argv);
+
+      _exit (-1);
+      /*NOTREACHED*/
+    }
+
+  /* now close the client side of the socket.. */
+  close (stdin_pipe[1]);
+  close (stdout_pipe[1]);
+
+  if (result == -1)
+    {
+      int save_errno;
+      save_errno = errno;
+      /* forking failed */
+      close (stdin_pipe[0]);
+      close (stdout_pipe[0]);
+      errno = save_errno;
+      return (-1);
+    }
+
+
+    /* trying to return information */
+    vmProxy->strMsgSend(in, "setFD:", vmProxy->intToOOP(stdin_pipe[0]), NULL);
+    vmProxy->strMsgSend(out, "setFD:", vmProxy->intToOOP(stdout_pipe[0]), NULL);
+    return result;
+}
+
+void
+gst_initModule (VMProxy * proxy)
+
+{
+  vmProxy = proxy;
+  vmProxy->defineCFunc ("gst_osprocess_fork_and_exec", gst_fork_and_exec);
+}
diff --git a/packages/osprocess/package.xml b/packages/osprocess/package.xml
new file mode 100644
index 0000000..2c85f93
--- /dev/null
+++ b/packages/osprocess/package.xml
@@ -0,0 +1,14 @@
+<package>
+  <name>OSProcess</name>
+  <namespace>OSProcess</namespace>
+  <module>gst-osprocess</module>
+
+  <test>
+    <sunit>OSProcess.ProcessTest</sunit>
+    <filein>OSProcessTests.st</filein>
+  </test>
+
+  <filein>OSProcess.st</filein>
+
+  <file>ChangeLog</file>
+</package>
--
1.7.10.4


_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: [RFC] osprocess: Introduce a simple sub-process package

Holger Freyther
On Fri, Dec 28, 2012 at 07:50:39PM +0100, Holger Hans Peter Freyther wrote:

Hi,

I started by looking at Gwenael's gst-osprocess but it didn't actually
implement to launch external apps and get the stream from the. It appears
to be only meant to fork gst itself and execute gst in a different process.

Can we host this in gst and probably move the cCall into the sysdep directory
and implement better integration with the SIGCHLD handling?

thanks
        holger

_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk