[jboss-jira] [JBoss JIRA] (JGRP-1944) jgroups does not recover properly when using UDP after ifdown / ifup

Bela Ban (JIRA) issues at jboss.org
Thu Jul 23 05:29:03 EDT 2015


     [ https://issues.jboss.org/browse/JGRP-1944?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Bela Ban updated JGRP-1944:
---------------------------
    Steps to Reproduce: See attached program  (was: 1) Start-up jgroups and bind it to a specific address
2) When started, do: ifdown <interface>
3) wait a while
4) Do: ifup <interface>

I would expect jgroups to recover after ifup is performed but its not. A simple class to demonstrate the problem:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * Demo class that auto recovers after ifdown/ifup
 */
public class AutoRecoverMulticast {
    private static final byte[] DATA = "test".getBytes(); // Dummy data
    private static final int MCAST_PORT = 45588;

    private final InetAddress mcastGroup;
    private final String bindingAddress;
    private MulticastSocket mcastSocket;
    private Thread senderThread;

    /**
     * Constructor
     *
     * @param bindingAddress
     *        Address to (re)bind to
     */
    public AutoRecoverMulticast(String bindingAddress) throws UnknownHostException {
        this.bindingAddress = bindingAddress;
        this.mcastGroup = InetAddress.getByName("230.5.6.7"); // JGroups default in MPING
    }

    /**
     * Starts the sender
     */
    void start() {
        stop();

        senderThread = new Thread(new Runnable() {
            @Override
            public void run() {
                loop(1000);
            }
        });
        senderThread.start();
    }

    /**
     * Stops the sender / app
     */
    void stop() {
        if (null != senderThread) {
            senderThread.interrupt();
        }
    }

    /**
     * Send messages
     *
     * @param interval
     */
    void loop(long interval) {
        while (!Thread.currentThread().isInterrupted()) {
            if (null == mcastSocket) {
                createSocket();
            }

            if (isValid(mcastSocket)) {
                try {
                    final DatagramPacket packet = new DatagramPacket(DATA, DATA.length, mcastGroup, MCAST_PORT);
                    mcastSocket.send(packet);
                    System.out.println("Datagram packet sent!");
                } catch (Exception e) {
                    System.err.println("Failed sending datagram packet");
                    e.printStackTrace();
                }
            } else {
                System.err.println("Multicast socket not valid (yet), not sending packet");
                cleanupSocket();
            }

            try {
                Thread.sleep(interval);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    private void createSocket() {
        cleanupSocket();

        try {
            mcastSocket = new MulticastSocket(MCAST_PORT);
            mcastSocket.setTimeToLive(8);
mcastSocket.setInterface(InetAddress.getByName(bindingAddress));
            mcastSocket.joinGroup(mcastGroup);
        } catch (IOException e) {
            e.printStackTrace();
            cleanupSocket();
        }

    }

    /**
     * Close socket if present and clean-up
     */
    private void cleanupSocket() {
        if (null != mcastSocket) {
            try {
                mcastSocket.close();
            } catch (RuntimeException e) {
                e.printStackTrace();
            }
        }
        mcastSocket = null;
    }

    /**
     * Validates a (possibly) created {@link MulticastSocket} for multicast
     * sending capabilities
     *
     * @param socket
     *        Socket to validate
     * @return true if the socket is (most likely) in a correct state to send
     *         datagram packets, false otherwise
     */
    private boolean isValid(MulticastSocket socket) {
        if (null == socket) {
            return false;
        }

        try {
            NetworkInterface multicastInterface = socket.getNetworkInterface(); // Without With -Djava.net.preferIPv4Stack=true this will throw an exception
            if (null == multicastInterface) {
                return false;
            }

            if (!multicastInterface.supportsMulticast()) { // With -Djava.net.preferIPv4Stack=true this will throw an exception
                return false;
            }

            if (!multicastInterface.isUp()) {
                return false;
            }
        } catch (SocketException e) {
            // Interface is gone (always?)
            return false;
        }

        return true; // Everything seems to be fine
    }

    /**
     * App entry
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {
        if (args.length < 1) {
            System.err.println("Usage: <class> <bind address>");
            return;
        }

        final AutoRecoverMulticast app = new AutoRecoverMulticast(args[0]);

        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                app.stop();
            }
        });
        app.start();
    }
} )


> jgroups does not recover properly when using UDP after ifdown / ifup
> --------------------------------------------------------------------
>
>                 Key: JGRP-1944
>                 URL: https://issues.jboss.org/browse/JGRP-1944
>             Project: JGroups
>          Issue Type: Bug
>    Affects Versions: 3.6.4
>         Environment: Linux Ubutun 14.04 where the network cards are configured as bridges:
> auto bridge0
>     iface bridge0 inet dhcp
>     bridge_ports eth1
>     bridge_stp off
>     bridge_fd 0
>            Reporter: Bram Klein Gunnewiek
>            Assignee: Bela Ban
>             Fix For: 3.6.5
>
>         Attachments: AutoRecoverMulticast.java
>
>
>  When we bring the interface down and back up in a complete (udp.xml) configuration everything *seems* to be fine, however multicast traffic from the node that had the interface brought down is not received by other nodes. The node also doesn't receive any data from the other nodes. No exceptions are logged. I don't think the previous test was done correctly by me ... sorry .
> When we use TCP + MPING we see the stacktraces we had previously with UDP:
> 12:13:51.624 50644 [Timer-3,debug,shockvm-tn3-42192] ERROR unknown.jul.logger - failed sending discovery request
> java.io.IOException: Invalid argument
>         at java.net.PlainDatagramSocketImpl.send(Native Method) ~[na:1.7.0_79]
>         at java.net.DatagramSocket.send(DatagramSocket.java:697) ~[na:1.7.0_79]
>         at org.jgroups.protocols.MPING.sendMcastDiscoveryRequest(MPING.java:295) ~[jar:rsrc:jgroups-3.6.4.Final.jar!/:na]
>         at org.jgroups.protocols.PING.sendDiscoveryRequest(PING.java:61) [jar:rsrc:jgroups-3.6.4.Final.jar!/:na]
>         at org.jgroups.protocols.PING.findMembers(PING.java:31) [jar:rsrc:jgroups-3.6.4.Final.jar!/:na]
>         at org.jgroups.protocols.Discovery.findMembers(Discovery.java:244) [jar:rsrc:jgroups-3.6.4.Final.jar!/:na]
>         at org.jgroups.protocols.Discovery.down(Discovery.java:387) [jar:rsrc:jgroups-3.6.4.Final.jar!/:na]
>         at org.jgroups.protocols.MERGE3$InfoSender.run(MERGE3.java:382) [jar:rsrc:jgroups-3.6.4.Final.jar!/:na]
>         at org.jgroups.util.TimeScheduler3$Task.run(TimeScheduler3.java:287) [jar:rsrc:jgroups-3.6.4.Final.jar!/:na]
>         at org.jgroups.util.TimeScheduler3$RecurringTask.run(TimeScheduler3.java:321) [jar:rsrc:jgroups-3.6.4.Final.jar!/:na]
>         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_79]
>         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_79]
>         at java.lang.Thread.run(Thread.java:745) [na:1.7.0_79]
> (The exact message differs whether or not the -Djava.net.preferIPv4Stack=true argument is configured)
> A configuration that uses MPING also doesn't recover from ifdown/ifup.



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)


More information about the jboss-jira mailing list