5

I need some special kind of setup to controll a LED Wall. Sadly i cant really change the programming language i use. My setup looks like this:

Processing (some crazy java fork...) Sketch starts after Boot Process. The Processing Sketch scans a folder for subfolder (other sketches which can be started and controll the LED Wall) and starts a Webserver. The Server renders a List with all the scanned Folders. On Click the "Webserver" launches the selected Sketch via ProcessBuilder. The Processing Sketch looks like this:

import http.*;
import java.util.*;
import java.lang.*;

SimpleHTTPServer server;
String prog = "";
int ExitValue = 1;
ProcessBuilder preparedsketch;
Process runningsketch;

void setup() {
  SimpleHTTPServer.useIndexHtml = false;
  server = new SimpleHTTPServer(this);
  TemplateFileHandler templateHandler = new ResultFiles("index.ftl");
  server.createContext("", templateHandler);
}


class ResultFiles extends TemplateFileHandler {
  public ResultFiles(String templateFileName) {
    super(templateFileName);
  }
  void createMap() {
    Map<String, String> params = queryToMap();
    if (params.containsKey("prog")) {
      if (params.get("prog").equals(prog)) {
        println("Has not changed");
      } else {
        println("PrevProcess: " + runningsketch);
        if (runningsketch != null) {
          println("Killing: " + runningsketch);
          runningsketch.destroy();
        }
        prog = params.get("prog");
        try {
          runningsketch = new ProcessBuilder("/Users/kessleml/dev/pixelpusher/base/processing-quit.sh", "--sketch=/Users/kessleml/dev/pixelpusher/base/sketches/pixelpusher_colourcycle_halloween", "--run").start();
          // runningsketch = new ProcessBuilder("/usr/local/bin/processing-java", "--force", "--sketch=" + sketchPath("sketches/" + prog + "/"), "--no-java", "--run").start();
        } catch (IOException ex) {
          println(ex);
        }
        println("ProjChagned: " + prog);
        println("NewProcess: " + runningsketch);
      }
    }

    File files = new File(sketchPath("sketches"));
    String[] fileslist = files.list();
    addVariable("files", fileslist);
    addVariable("selectedprog", prog);
  }
}

Everything works till now. But of course i want to close a running (and looping) Sketch if i change (click on a other Sketch on the Website). The Problem is:

When i launch a selected Sketch via runninngsketch = new ProcessBuilder("Path/To/ProcessingCLI", "--sketch=Path/To/Selected/Sketch", "--run").start(); more than one process launches. The reason for this, is the ProcessingCLI File:

#!/bin/sh

# Prevents processing-java from stealing focus, see:
# https://github.com/processing/processing/issues/3996.
OPTION_FOR_HEADLESS_RUN=""
for ARG in "$@"
do
    if [ "$ARG" = "--build" ]; then
        OPTION_FOR_HEADLESS_RUN="-Djava.awt.headless=true"
    fi
done

cd "/Applications/Processing.app/Contents/Java" && /Applications/Processing.app/Contents/PlugIns/jdk1.8.0_74.jdk/Contents/Home/jre/bin/java -Djna.nosys=true $OPTION_FOR_HEADLESS_RUN -cp "ant-launcher.jar:ant.jar:core.jar:jna.jar:pde.jar:core/library/core.jar:core/library/gluegen-rt-natives-linux-amd64.jar:core/library/gluegen-rt-natives-linux-armv6hf.jar:core/library/gluegen-rt-natives-linux-i586.jar:core/library/gluegen-rt-natives-macosx-universal.jar:core/library/gluegen-rt-natives-windows-amd64.jar:core/library/gluegen-rt-natives-windows-i586.jar:core/library/gluegen-rt.jar:core/library/jogl-all-natives-linux-amd64.jar:core/library/jogl-all-natives-linux-armv6hf.jar:core/library/jogl-all-natives-linux-i586.jar:core/library/jogl-all-natives-macosx-universal.jar:core/library/jogl-all-natives-windows-amd64.jar:core/library/jogl-all-natives-windows-i586.jar:core/library/jogl-all.jar:modes/java/mode/antlr.jar:modes/java/mode/classpath-explorer-1.0.jar:modes/java/mode/com.ibm.icu.jar:modes/java/mode/JavaMode.jar:modes/java/mode/jdi.jar:modes/java/mode/jdimodel.jar:modes/java/mode/jdtCompilerAdapter.jar:modes/java/mode/jsoup-1.7.1.jar:modes/java/mode/org.eclipse.core.contenttype.jar:modes/java/mode/org.eclipse.core.jobs.jar:modes/java/mode/org.eclipse.core.resources.jar:modes/java/mode/org.eclipse.core.runtime.jar:modes/java/mode/org.eclipse.equinox.common.jar:modes/java/mode/org.eclipse.equinox.preferences.jar:modes/java/mode/org.eclipse.jdt.core.jar:modes/java/mode/org.eclipse.osgi.jar:modes/java/mode/org.eclipse.text.jar:modes/java/mode/org.netbeans.swing.outline.jar" processing.mode.java.Commander "$@"

So the ProcessBuilder starts three processes: One sh-process which launches two Java-Children-Processes. When i use runningsketch.destroy() it only kills the sh process. The two Java-processes continue running. (Not sure if this is also because of this bug: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4770092 since i am developing on MacOS Yosemite. The final Product should run on a Linux Machine.)

My solution was to write a new sh-script which kills all of its children via trap:

#!/bin/sh

OPTION_FOR_HEADLESS_RUN=""

function killAllChildren {
    kill -9 -$(ps -o pgid= $$ | grep -o '[0-9]*')
}

trap killAllChildren SIGTERM SIGKILL
# trap "trap - SIGTERM && kill -- $$" SIGINT SIGTERM EXIT

cd "/Applications/Processing.app/Contents/Java"

/Applications/Processing.app/Contents/PlugIns/jdk1.8.0_74.jdk/Contents/Home/jre/bin/java -Djna.nosys=true $OPTION_FOR_HEADLESS_RUN -cp "ant-launcher.jar:ant.jar:core.jar:jna.jar:pde.jar:core/library/core.jar:core/library/gluegen-rt-natives-linux-amd64.jar:core/library/gluegen-rt-natives-linux-armv6hf.jar:core/library/gluegen-rt-natives-linux-i586.jar:core/library/gluegen-rt-natives-macosx-universal.jar:core/library/gluegen-rt-natives-windows-amd64.jar:core/library/gluegen-rt-natives-windows-i586.jar:core/library/gluegen-rt.jar:core/library/jogl-all-natives-linux-amd64.jar:core/library/jogl-all-natives-linux-armv6hf.jar:core/library/jogl-all-natives-linux-i586.jar:core/library/jogl-all-natives-macosx-universal.jar:core/library/jogl-all-natives-windows-amd64.jar:core/library/jogl-all-natives-windows-i586.jar:core/library/jogl-all.jar:modes/java/mode/antlr.jar:modes/java/mode/classpath-explorer-1.0.jar:modes/java/mode/com.ibm.icu.jar:modes/java/mode/JavaMode.jar:modes/java/mode/jdi.jar:modes/java/mode/jdimodel.jar:modes/java/mode/jdtCompilerAdapter.jar:modes/java/mode/jsoup-1.7.1.jar:modes/java/mode/org.eclipse.core.contenttype.jar:modes/java/mode/org.eclipse.core.jobs.jar:modes/java/mode/org.eclipse.core.resources.jar:modes/java/mode/org.eclipse.core.runtime.jar:modes/java/mode/org.eclipse.equinox.common.jar:modes/java/mode/org.eclipse.equinox.preferences.jar:modes/java/mode/org.eclipse.jdt.core.jar:modes/java/mode/org.eclipse.osgi.jar:modes/java/mode/org.eclipse.text.jar:modes/java/mode/org.netbeans.swing.outline.jar" processing.mode.java.Commander "$@"

But somehow, also this doesnt work. Even with starting the new sh-script and sending for example a SIGTERM to the started sh-process, doesnt destroy the two Java-Processes neither the sh-process.

5
  • I think there should be no blank after the = in your killAllChildren function. i.e. -o pgid=$$ Commented May 11, 2016 at 13:33
  • Yeah, seems like this was a typo (i am trying to solve this problem since days, so the code got a little bit messed up. Sorry about that). Anyways, it doesnt work even without the space. I made some more tests. The running sh-process doesnt react on SIGTERM at all. Is my trap line not working? When i send a SIGKILL to the sh-process it does get shut down, but not its children. They will drop out of the ProcessTree and act like Orphan-Processes. Commented May 11, 2016 at 14:42
  • Another odd phenomenon: When i set up a simple trap like trap "echo $$" SIGINT SIGTERM EXIT and try to SIGTERM or SIGKILL the sh-process nothing happens or the sh-process simply shuts down without executing the trap (see comment above). But when i SIGTERM or SIGKILL one of the Java Processes, the trap gets executed and i recive my test message (the PID) and the Java Applets shut down. It really seems like i am missing something here. Commented May 11, 2016 at 14:50
  • First, you can't catch SIGKILL. Also the SIGTERM may be ignored by interactive shells, So perhaps these are unlucky signals to use. Try SIGUSR1 for instance, that should work as expected. Commented May 11, 2016 at 15:17
  • Thanks for your comment, but it also doesnt work with SIGUSR1. I dont get any reaction at all when i send a SIGUSR1 Signal to the sh process, even when i set up the trap for SIGUSR1. Also: The java.lang.destroy() Command sends a SIGTERM signal. So trapping SIGUSR1 would not help much. Commented May 12, 2016 at 11:16

1 Answer 1

2

I found the solution:

Java sends a SIGTERM signal, so i had to trap this signal. But the java/processing file wasnt the problem, the sh-script didn work as intended.

I had to add & wait to the and of my script. Otherwise SIGTERM cant be trapped (see this post: https://apple.stackexchange.com/questions/123631/why-does-a-shell-script-trapping-sigterm-work-when-run-manually-but-not-when-ru).

Also the killing process didn work out right. I have to kill all children, the sh-script itself BUT not the parent-processes of the sh-script (in this use case the webserver etc.). So i wrote a function to find all children processes and kill them. Things like kill -9 -$(ps -o pgid= $$ | grep -o '[0-9]*') didnt work since they killed the whole tree. In the end the sh-file looks like this:

#!/bin/sh

function killAllChildren {
    getChild $$
    pkill -TERM -P $$
}

function getChild() {
    cpids=`pgrep -P $1|xargs`
    for cpid in $cpids;
    do
        kill -15 $cpid
        getChild $cpid
    done
}

trap killAllChildren SIGUSR1 SIGTERM SIGKILL EXIT

cd "/Applications/Processing.app/Contents/Java"

/Applications/Processing.app/Contents/PlugIns/jdk1.8.0_74.jdk/Contents/Home/jre/bin/java -Djna.nosys=true -cp "ant-launcher.jar:ant.jar:core.jar:jna.jar:pde.jar:core/library/core.jar:core/library/gluegen-rt-natives-linux-amd64.jar:core/library/gluegen-rt-natives-linux-armv6hf.jar:core/library/gluegen-rt-natives-linux-i586.jar:core/library/gluegen-rt-natives-macosx-universal.jar:core/library/gluegen-rt-natives-windows-amd64.jar:core/library/gluegen-rt-natives-windows-i586.jar:core/library/gluegen-rt.jar:core/library/jogl-all-natives-linux-amd64.jar:core/library/jogl-all-natives-linux-armv6hf.jar:core/library/jogl-all-natives-linux-i586.jar:core/library/jogl-all-natives-macosx-universal.jar:core/library/jogl-all-natives-windows-amd64.jar:core/library/jogl-all-natives-windows-i586.jar:core/library/jogl-all.jar:modes/java/mode/antlr.jar:modes/java/mode/classpath-explorer-1.0.jar:modes/java/mode/com.ibm.icu.jar:modes/java/mode/JavaMode.jar:modes/java/mode/jdi.jar:modes/java/mode/jdimodel.jar:modes/java/mode/jdtCompilerAdapter.jar:modes/java/mode/jsoup-1.7.1.jar:modes/java/mode/org.eclipse.core.contenttype.jar:modes/java/mode/org.eclipse.core.jobs.jar:modes/java/mode/org.eclipse.core.resources.jar:modes/java/mode/org.eclipse.core.runtime.jar:modes/java/mode/org.eclipse.equinox.common.jar:modes/java/mode/org.eclipse.equinox.preferences.jar:modes/java/mode/org.eclipse.jdt.core.jar:modes/java/mode/org.eclipse.osgi.jar:modes/java/mode/org.eclipse.text.jar:modes/java/mode/org.netbeans.swing.outline.jar" processing.mode.java.Commander "$@" & wait
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.