2

I have a akka task running in the background to listen to UDP packages. However, when I do this, and I make a code change the system recompiles, but then stalls/hangs and I need to stop completely and restart (which takes a good bit of time if in needs to be done after every change). When I don't start the Hakka task it works fine. This is the console output:

[info] play - database [default] connected at jdbc:h2:mem:play
[info] play - Starting application default Akka system.
[info] application - Starting UDP server
[info] play - Application started (Dev)
[debug] application - Ready to receive broadcast packets!
[info] Compiling 1 Scala source and 1 Java source to /Users/Luuk/Documents/Java/temperature-control/target/scala-2.11/classes...
[info] Compiling 1 Scala source and 1 Java source to /Users/Luuk/Documents/Java/temperature-control/target/scala-2.11/classes...
[success] Compiled in 6s
[info] Compiling 1 Scala source to /Users/Luuk/Documents/Java/temperature-control/target/scala-2.11/classes...

--- (RELOAD) ---

[info] play - Shutdown application default Akka system.

I am using IDEA 14 .

This is my Global: public class Global extends GlobalSettings {

@Override
public void onStart(Application app) {
    if (SensorRole.find.findRowCount() != SensorRole.RoleName.values().length) {
        for (SensorRole.RoleName roleName : SensorRole.RoleName.values()) {
            SensorRole newRole = new SensorRole();
            newRole.name = roleName.toString();
            newRole.save();
        }


    }

    ActorRef instance = Akka.system().actorOf(Props.create(UDPBroadcastServer.class), "UDPServer");
    instance.tell("Start", ActorRef.noSender());

    super.onStart(app);
}

@Override
public void onStop(Application app){
    Logger.debug("Stopping system...");
    Akka.system().shutdown();

    super.onStop(app);
}

}

and UDPBroadcastServer:

public class UDPBroadcastServer extends UntypedActor {

    DatagramSocket socket;
    boolean stop;

    @Override
    public void postStop() throws Exception {
        super.postStop();
        stop = true;
        Logger.info("Master Killed");
    }

    @Override
    public void onReceive(Object command) throws Exception {
        Logger.info("Starting UDP server");
        stop = false;
    String action = (String) command;
    if (action.equals("Start")) {
        try {
            //Keep a socket open to listen to all the UDP trafic that is destined for this port
            socket = new DatagramSocket(8888, InetAddress.getByName("0.0.0.0"));

            socket.setBroadcast(true);

            while (!stop) {
                Logger.debug("Ready to receive broadcast packets!");

                //Receive a packet
                byte[] recvBuf = new byte[15000];
                packet = new DatagramPacket(recvBuf, recvBuf.length);
                socket.receive(packet);

                //Packet received
                Logger.debug("Discovery packet received from: " + packet.getAddress().getHostAddress());
                Logger.debug("Packet received; data: " + new String(packet.getData()));

                //See if the packet holds the right command (message)
                String message = new String(packet.getData()).trim();
                if (message.equals("DISCOVER_TEMPSERVER_REQUEST")) {
                    byte[] sendData = "DISCOVER_TEMPSERVER_RESPONSE".getBytes();

                    //Send a response
                    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, packet.getAddress(), packet.getPort());
                    socket.send(sendPacket);

                    Logger.debug("Sent packet to: " + sendPacket.getAddress().getHostAddress());
                }
            }
        } catch (IOException ex) {
            Logger.error("Problem with UDP server:" + ex.getLocalizedMessage());
        }
    } else if (action.equals("Stop")) {
        Logger.debug("Trying to stop process!");
        stop = true;
        if(packet != null) packet = null;
        if(socket.isConnected()) socket.close();
    }
}

[Edit]: As per commend, I am trying to stop the task manually. However, I cannot get a handle back on the ActorRef. I am trying to do this:

    ActorRef test = Akka.system().actorFor("//application/user/UDPServer");
    test.tell("Stop", ActorRef.noSender());
    Logger.debug("Path: " + test.path());
    Akka.system().stop(test);

But 'Stop' is never received by the 'onReceive' of the Actor.

Luuk D. Jansen
  • 4,402
  • 8
  • 47
  • 90
  • I would gess your actor is blocked on `socket.receive(packet)`. From the doc, you can understand why: `This method blocks until a datagram is received.`, thus your stop flag makes no sense. – Mon Calamari Jan 26 '15 at 11:45
  • Ok, that makes sense. I am trying now to close the socket, but don't seem to be able to get a handle on the tsk already active. I use test.tell("Stop", ActorRef.noSender()); per the code above, but do not receive anything. Maybe I should create a separate thread for the socket. – Luuk D. Jansen Jan 26 '15 at 12:13
  • This might help: http://stackoverflow.com/questions/4425350/how-to-terminate-a-thread-blocking-on-socket-io-operation-instantly – Mon Calamari Jan 26 '15 at 12:17
  • I put the socket in a separate thread, and now the olnrecieve can receive the call, and close the socket and everything works perfectly (I added the stop on the onStop of the Play Global.) If you would like to put the answer in then I will accept it as you pointed out the problem. – Luuk D. Jansen Jan 26 '15 at 12:35
  • Hi, thanks. I copied these comments to the answer. – Mon Calamari Jan 26 '15 at 14:12

1 Answers1

0

I would guess your actor is blocked on socket.receive(packet). From the doc, you can understand why: This method blocks until a datagram is received, thus your stop flag makes no sense. This might help: How to terminate a thread blocking on socket IO operation instantly?

Community
  • 1
  • 1
Mon Calamari
  • 4,403
  • 3
  • 26
  • 44