aboutsummaryrefslogtreecommitdiffstats
path: root/libfsoframework
diff options
context:
space:
mode:
authorMichael 'Mickey' Lauer <mickey@vanille-media.de>2009-12-16 13:31:12 +0100
committerMichael 'Mickey' Lauer <mickey@vanille-media.de>2009-12-16 13:31:12 +0100
commitbd2b7183d37ad579c1848b74bbfcee7a40b01383 (patch)
tree8b9fc8453c779389831712ea49cc222dd31c94e1 /libfsoframework
parent9943308ce82567d1c1f6c22294b18dc56c00a660 (diff)
downloadcornucopia-bd2b7183d37ad579c1848b74bbfcee7a40b01383.tar.gz
cornucopia-bd2b7183d37ad579c1848b74bbfcee7a40b01383.tar.bz2
cornucopia-bd2b7183d37ad579c1848b74bbfcee7a40b01383.zip
libfsoframework: add GProcessGuard, spawning an external process and guarding it
Diffstat (limited to 'libfsoframework')
-rw-r--r--libfsoframework/fsoframework/Makefile.am2
-rw-r--r--libfsoframework/fsoframework/process.vala90
-rw-r--r--libfsoframework/fsoframework/syncasync.vala73
-rw-r--r--libfsoframework/tests/Makefile.am13
-rw-r--r--libfsoframework/tests/testinotifier.vala2
-rwxr-xr-xlibfsoframework/tests/testprocess148
6 files changed, 327 insertions, 1 deletions
diff --git a/libfsoframework/fsoframework/Makefile.am b/libfsoframework/fsoframework/Makefile.am
index c0634e32..7711125a 100644
--- a/libfsoframework/fsoframework/Makefile.am
+++ b/libfsoframework/fsoframework/Makefile.am
@@ -26,7 +26,9 @@ libfsoframework_la_VALASOURCES = \
kobjectnotifier.vala \
object.vala \
plugin.vala \
+ process.vala \
subsystem.vala \
+ syncasync.vala \
$(NULL)
libfsoframework_la_SOURCES = \
diff --git a/libfsoframework/fsoframework/process.vala b/libfsoframework/fsoframework/process.vala
new file mode 100644
index 00000000..ff4e6b67
--- /dev/null
+++ b/libfsoframework/fsoframework/process.vala
@@ -0,0 +1,90 @@
+/**
+ * Copyright (C) 2009 Michael 'Mickey' Lauer <mlauer@vanille-media.de>
+ *
+ * This 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 of the License, or (at your option) any later version.
+
+ * This 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @interface FsoFramework.IProcessGuard
+ **/
+public interface FsoFramework.IProcessGuard : GLib.Object
+{
+ public abstract bool launch( string[] command );
+ public abstract void kill( int sig = Posix.SIGTERM );
+
+ public signal void running( FsoFramework.IProcessGuard self );
+ public signal void stopped( FsoFramework.IProcessGuard self );
+}
+
+/**
+ * @class FsoFramework.GProcessGuard
+ **/
+public class FsoFramework.GProcessGuard : FsoFramework.IProcessGuard, GLib.Object
+{
+ private Pid pid;
+ private uint watch;
+
+ public bool launch( string[] command )
+ {
+ if ( pid != (Pid)0 )
+ {
+ warning( @"Can't launch $(command[0]); already running as pid %d".printf( (int)pid ) );
+ return false;
+ }
+
+ var res = 0;
+ try
+ {
+ GLib.Process.spawn_async( GLib.Environment.get_variable( "PWD" ),
+ command,
+ null,
+ GLib.SpawnFlags.DO_NOT_REAP_CHILD | GLib.SpawnFlags.SEARCH_PATH,
+ null,
+ out pid );
+ }
+ catch ( SpawnError e )
+ {
+ warning( @"Can't spawn $(command[0]): $(strerror(errno))" );
+ return false;
+ }
+
+ watch = GLib.ChildWatch.add( pid, onChildWatchEvent );
+ this.running( this ); // SIGNAL
+ return true;
+ }
+
+ public void kill( int sig = Posix.SIGTERM )
+ {
+ GLib.Process.close_pid( pid );
+ Posix.kill( (Posix.pid_t)pid, sig );
+ if ( watch > 0 )
+ {
+ GLib.Source.remove( watch );
+ }
+ }
+
+ //
+ // private API
+ //
+ public void onChildWatchEvent( Pid pid, int status )
+ {
+#if DEBUG
+ debug( "CHILD WATCH EVENT FOR %d: %d", (int)pid, status );
+#endif
+ assert( this.pid == pid );
+ this.stopped( this ); // SIGNAL
+ }
+}
diff --git a/libfsoframework/fsoframework/syncasync.vala b/libfsoframework/fsoframework/syncasync.vala
new file mode 100644
index 00000000..9b3973ae
--- /dev/null
+++ b/libfsoframework/fsoframework/syncasync.vala
@@ -0,0 +1,73 @@
+/**
+ * Copyright (C) 2009 Michael 'Mickey' Lauer <mlauer@vanille-media.de>
+ *
+ * This 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 of the License, or (at your option) any later version.
+
+ * This 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+public class FsoFramework.SyncWrapper : GLib.Object
+{
+ protected GLib.VoidFunc func;
+ protected GLib.MainLoop loop;
+
+ public SyncWrapper( owned GLib.VoidFunc func )
+ {
+ this.func = func;
+ loop = new MainLoop();
+ // unfortunately a closure does not work here, ideally we'd just:
+ // Idle.add( () => { func(); loop.quit(); return false; } );
+ // however vala bails out with some target_func not found then
+ Idle.add( onIdle );
+ loop.run();
+ }
+
+ protected virtual bool onIdle()
+ {
+ func();
+ loop.quit();
+ return false;
+ }
+}
+
+public class FsoFramework.WaitForPredicate : GLib.Object
+{
+ private GLib.SourceFunc func;
+ private GLib.MainLoop loop;
+ private uint secs;
+ public bool timeout;
+
+ public WaitForPredicate( uint secs, owned GLib.SourceFunc func )
+ {
+ this.secs = secs;
+ this.func = func;
+ loop = new MainLoop();
+ Idle.add( onIdle );
+ loop.run();
+ }
+
+ protected bool onIdle()
+ {
+ var now = time_t();
+ var then = now + (time_t) secs;
+
+ while ( time_t() < then && func() )
+ {
+ loop.get_context().iteration( false );
+ }
+ timeout = func();
+ loop.quit();
+ return false;
+ }
+}
diff --git a/libfsoframework/tests/Makefile.am b/libfsoframework/tests/Makefile.am
index be8d568e..199296ee 100644
--- a/libfsoframework/tests/Makefile.am
+++ b/libfsoframework/tests/Makefile.am
@@ -189,6 +189,19 @@ $(testsoundsystem_SOURCES): $(testsoundsystem_VALASOURCES)
testsoundsystem_LDADD = $(progs_ldadd)
EXTRA_DIST += $(testsoundsystem_VALASOURCES)
+#
+# process test
+#
+TEST_PROGS += testprocess
+testprocess_VALASOURCES = testprocess.vala
+testprocess_SOURCES = testprocess.c
+$(testprocess_SOURCES): $(testprocess_VALASOURCES)
+ $(VALAC) $(VALAC_ARGS) $^
+ touch $@
+testprocess_LDADD = $(progs_ldadd)
+EXTRA_DIST += $(testprocess_VALASOURCES)
+
+
CLEANFILES = \
$(TEST_PROGS) \
*.? \
diff --git a/libfsoframework/tests/testinotifier.vala b/libfsoframework/tests/testinotifier.vala
index 65ed41e3..43abef04 100644
--- a/libfsoframework/tests/testinotifier.vala
+++ b/libfsoframework/tests/testinotifier.vala
@@ -32,7 +32,7 @@ public void myCallback( Linux.InotifyMaskFlags flags, uint32 cookie, string? nam
void test_inotifier_add()
//===========================================================================
{
- INotifier.add( "/tmp/foo", Linux.InotifyMaskFlags.CREATE, myCallback );
+ INotifier.add( "/tmp/foo", Linux.InotifyMaskFlags.MODIFY, myCallback );
loop = new MainLoop();
loop.run();
}
diff --git a/libfsoframework/tests/testprocess b/libfsoframework/tests/testprocess
new file mode 100755
index 00000000..4e18211e
--- /dev/null
+++ b/libfsoframework/tests/testprocess
@@ -0,0 +1,148 @@
+#! /bin/sh
+
+# testprocess - temporary wrapper script for .libs/testprocess
+# Generated by ltmain.sh (GNU libtool) 2.2.6 Debian-2.2.6a-4
+#
+# The testprocess program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='/bin/sed -e 1s/^X//'
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command="(cd /local/pkg/fso/cornucopia/libfsoframework/tests; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; LD_LIBRARY_PATH=/usr/local/lib; export LD_LIBRARY_PATH; PATH=/home/mickey/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/sbin:/usr/sbin:/usr/local/sbin:/usr/bin:/bin:/usr/X11R6/bin:/usr/local/bin:/local/pkg/oe/bitbake/bin:.:/home/mickey/bin:/usr/local/texlive/2008/bin/i686-linux; export PATH; gcc -g -O2 -o \$progdir/\$file testprocess.o -L/lib -ldbus-glib-1 -ldbus-1 -lpthread -lrt /usr/lib/libasound.so -L/usr/local/lib /usr/local/lib/libfsobasics.so /usr/lib/libgio-2.0.so /usr/lib/libgobject-2.0.so /usr/lib/libgmodule-2.0.so /usr/lib/libglib-2.0.so ../fsoframework/.libs/libfsoframework.so -Wl,-rpath -Wl,/local/pkg/fso/cornucopia/libfsoframework/fsoframework/.libs)"
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version='2.2.6'
+ notinst_deplibs=' ../fsoframework/libfsoframework.la'
+else
+ # When we are sourced in execute mode, $file and $ECHO are already set.
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ ECHO="echo"
+ file="$0"
+ # Make sure echo works.
+ if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then
+ # Yippee, $ECHO works!
+ :
+ else
+ # Restart under the correct shell, and then maybe $ECHO will work.
+ exec /bin/sh "$0" --no-reexec ${1+"$@"}
+ fi
+ fi
+
+ # Find the directory that this script lives in.
+ thisdir=`$ECHO "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "x$thisdir" = "x$file" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
+ while test -n "$file"; do
+ destdir=`$ECHO "X$file" | $Xsed -e 's%/[^/]*$%%'`
+
+ # If there was a directory component, then change thisdir.
+ if test "x$destdir" != "x$file"; then
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+ *) thisdir="$thisdir/$destdir" ;;
+ esac
+ fi
+
+ file=`$ECHO "X$file" | $Xsed -e 's%^.*/%%'`
+ file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
+ done
+
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+ if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
+ # special case for '.'
+ if test "$thisdir" = "."; then
+ thisdir=`pwd`
+ fi
+ # remove .libs from thisdir
+ case "$thisdir" in
+ *[\\/].libs ) thisdir=`$ECHO "X$thisdir" | $Xsed -e 's%[\\/][^\\/]*$%%'` ;;
+ .libs ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=`cd "$thisdir" && pwd`
+ test -n "$absdir" && thisdir="$absdir"
+
+ program=lt-'testprocess'
+ progdir="$thisdir/.libs"
+
+ if test ! -f "$progdir/$program" ||
+ { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
+ test "X$file" != "X$progdir/$program"; }; then
+
+ file="$$-$program"
+
+ if test ! -d "$progdir"; then
+ mkdir "$progdir"
+ else
+ rm -f "$progdir/$file"
+ fi
+
+ # relink executable if necessary
+ if test -n "$relink_command"; then
+ if relink_command_output=`eval $relink_command 2>&1`; then :
+ else
+ echo "$relink_command_output" >&2
+ rm -f "$progdir/$file"
+ exit 1
+ fi
+ fi
+
+ mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
+ { rm -f "$progdir/$program";
+ mv -f "$progdir/$file" "$progdir/$program"; }
+ rm -f "$progdir/$file"
+ fi
+
+ if test -f "$progdir/$program"; then
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ # Run the actual program with our arguments.
+
+ exec "$progdir/$program" ${1+"$@"}
+
+ $ECHO "$0: cannot exec $program $*" 1>&2
+ exit 1
+ fi
+ else
+ # The program doesn't exist.
+ $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
+ $ECHO "This script is just a wrapper for $program." 1>&2
+ echo "See the libtool documentation for more information." 1>&2
+ exit 1
+ fi
+fi