How to wait until environment is non-headless?

1.6k views Asked by At

I've created a Java server that boots up with Ubuntu 12.04 and I've one problem: my code needs a non-headless (or headfull) environment to work, otherwise it throws a HeadlessException:

java.awt.AWTException: headless environment
at java.awt.Robot.<init>(Robot.java:91)
at remote_control.RobotThread.run(RobotThread.java:35)
at java.lang.Thread.run(Thread.java:745)

But it seems that my .jar is started before X server on startup, so I'm always getting the "HeadlessException". To make my JAR start with my system I have done something like:

sudo update-rc.d my_script_to_initiate_my_jar defaults 99 01

I haven't found a way to boot the JAR after X server, so I think the best way to solve this problem is using busy waiting inside my code. I already checked a lot of questions (at StackOverflow and at Google) and I found some common solutions:

// First solution
while (GraphicsEnvironment.isHeadless()) {
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

// Second solution
GraphicsEnvironment ge;
do {
    ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
} while (ge.isHeadless());

Unfortunately these solutions didn't work: isHeadless() always returns true, so it never exit the loop. And yes, at this time I was already using Unity (the Ubuntu graphical interface), so I already have a "headfull environment". Sorry if I made some mistake, but I'm very newbie with UNIX / Linux.

If you need any further information, please ask me and I will provide it. The solution also must be non-GUI-specific (e.g: only works on GNOME or Unity, must work in all of them).

Edit

Following you can check my .sh script that is inside /etc/init.d/ and is responsible to startup the JAR with the system. Contain the script provided by @that-other-guy .

#!/bin/sh
SERVICE_NAME=labspy_client
PATH_TO_JAR=/var/lib/LabSpy/Student.jar
PID_PATH_NAME=/tmp/labspy_client_pid
case $1 in
    start)
        echo "Starting $SERVICE_NAME ..."
        if [ ! -f $PID_PATH_NAME ]; then
                export DISPLAY=:0
                until xwininfo -root > /dev/null
                do
                    sleep 5
                done
                nohup /opt/java/bin/java -jar $PATH_TO_JAR /tmp 2>> /var/log/labspy_stdout >> /var/log/labspy_stderr &
                        echo $! > $PID_PATH_NAME
                echo "$SERVICE_NAME started ..."
        else
                echo "$SERVICE_NAME is already running ..."
        fi
    ;;
    stop)
        if [ -f $PID_PATH_NAME ]; then
            PID=$(cat $PID_PATH_NAME);
            echo "$SERVICE_NAME stoping ..."
            kill $PID;
            echo "$SERVICE_NAME stopped ..."
            rm $PID_PATH_NAME
        else
            echo "$SERVICE_NAME is not running ..."
        fi
    ;;
    restart)
        if [ -f $PID_PATH_NAME ]; then
            PID=$(cat $PID_PATH_NAME);
            echo "$SERVICE_NAME stopping ...";
            kill $PID;
            echo "$SERVICE_NAME stopped ...";
            rm $PID_PATH_NAME
            echo "$SERVICE_NAME starting ..."
            nohup java -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &
                        echo $! > $PID_PATH_NAME
            echo "$SERVICE_NAME started ..."
        else
            echo "$SERVICE_NAME is not running ..."
        fi
    ;;
esac 
1

There are 1 answers

12
that other guy On BEST ANSWER

The display to use for a graphical program is determined using the DISPLAY environment variable. This is normally set by and inherited from the X session.

If you think an appropriate display server will be up and running in the near future, you can guess at its display number -- probably :0 -- and wait for it to respond to things.

I really wouldn't trust Java to re-check whether a display is functional after it first initializes, so here's a shell script loop:

export DISPLAY=:0
export XAUTHORITY="/home/youruser/.Xauthority"
until xwininfo -root > /dev/null
do
  sleep 5
done
echo "X server is now running"

This is a highly anti-Unix solution caused by your Windows style requirement of assuming that there is exactly one screen and that you need to take control of it.

Well behaving Unix programs would not work against the system like this, and would instead leave it to the user to start the server on the display of their choice.