2.0 almost finished, reconnect issues, and request for feedback

72 views
Skip to first unread message

Leon Blakey

unread,
Jun 16, 2013, 7:21:06 PM6/16/13
to pirc...@googlegroups.com
Hello everyone!

Its been a long time, but 2.0 is nearing completion. I've finished the bulk of the changes and will start working on javadoc, documentation, and remaining cleanup.

One of the latest changes was finally fixing reconnect issues that people on the mailing list, issue tracker, and emails to me. This has been a difficult problem to fix but the new method should be more reliable and allow you to better decide how to handle exceptions. Unfortunately the only way to do this was to have you call PircBotX.startBot() instead of connect(), which is now marked protected. See https://code.google.com/p/pircbotx/wiki/MigrationGuide2#Better_Connection_Handling for more information

There (current) full list of changes is at https://code.google.com/p/pircbotx/wiki/ChangeLog

As I start wrapping up 2.0 though I am needing feedback from you. Do you think the changes are the best option? What doesn't make sense? Are you generally happy with the release? Any suggestion or comment would be helpful.

-Leon

Joerg Stoever

unread,
Jul 15, 2013, 4:20:26 PM7/15/13
to pirc...@googlegroups.com
Trying the Sonatype version of the 2.0 snapshot you recommended per email, I found that I was unable to get the java application using the bot to shut down at all. System.exit(0) somehow was blocked by some code in the 2.0 bot, and both bot.shutdown() as well as bot.shutdown(true) stall as far as I can tell forever. The bot leaves IRC, but the JVM never terminates. I demonstrated this in a short SSCEE:

import org.pircbotx.Configuration;
import org.pircbotx.PircBotX;
import org.pircbotx.hooks.ListenerAdapter;
import org.pircbotx.hooks.events.MessageEvent;

public class SSCEE {
    public static void main(String[] args) {
        Configuration<PircBotX> configuration = new Configuration.Builder<>().setName("PircBotX")
                .addListener(new ListenerAdapter<PircBotX>() {
                    public void onMessage(MessageEvent<PircBotX> event) {
                        if ("!restart".equalsIgnoreCase(event.getMessage())) {
                            System.out.println("Restart command issues by " + event.getUser());
                            event.getBot().shutdown(true);
                            System.exit(0);
                        }
                    }
                }).setServerHostname("irc.freenode.net").addAutoJoinChannel("#pircbotx").buildConfiguration();
        PircBotX bot = new PircBotX(configuration);

        try {
            bot.startBot();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

Joerg Stoever

unread,
Jul 16, 2013, 1:48:40 PM7/16/13
to pirc...@googlegroups.com
I have some more info:

Apparently, the problem is attempting to shut down the bot from the Listener event thread - the following code sort of successfully calls the shutdown code without blocking:

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException ignored) {}
                    bot.shutdown();
                }
            }).start();

That being said, there are still a few issues: System.exit is still broken JVM WIDE if PircBotX 2.0 is ever started, no way of calling shutdown, whether it is with true, false or no argument results in actually shutting down the bot (it always restarts), and I'm not sure if the way that works is even remotely thread safe.

Joerg Stoever

unread,
Jul 16, 2013, 4:20:24 PM7/16/13
to pirc...@googlegroups.com
Additional note: .shutdown appears to be broken in the 1.9 branch as well. No combination of shutdown(whatever) and disconnect() seem to be able to actually shut the bot down instead of restarting and reconnecting it. System.exit has to be used even in 1.9 to shut down and reports "Your implementation of PircBotX is faulty".

Joerg Stoever

unread,
Jul 23, 2013, 5:56:52 PM7/23/13
to pirc...@googlegroups.com
System.exit() in 1.9 also randomly freezes forever with a stacktrace like this:

1374616471613 ### java.net.SocketException: Socket closed
1374616471613 ###       at java.net.SocketInputStream.read(SocketInputStream.java:183)
1374616471613 ###       at java.net.SocketInputStream.read(SocketInputStream.java:121)
1374616471613 ###       at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
1374616471613 ###       at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
1374616471613 ###       at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
1374616471613 ###       at java.io.InputStreamReader.read(InputStreamReader.java:184)
1374616471613 ###       at java.io.BufferedReader.fill(BufferedReader.java:154)
1374616471613 ###       at java.io.BufferedReader.readLine(BufferedReader.java:317)
1374616471613 ###       at java.io.BufferedReader.readLine(BufferedReader.java:382)
1374616471613 ###       at org.pircbotx.InputThread.run(InputThread.java:81)
Exception in thread "bot1-input" java.lang.RuntimeException: Waiting for mode response interrupted
        at org.pircbotx.Channel.getMode(Channel.java:133)
        at org.pircbotx.Channel.getModeArgument(Channel.java:182)
        at org.pircbotx.Channel.getChannelKey(Channel.java:239)
        at org.pircbotx.PircBotX.shutdown(PircBotX.java:2872)
        at org.pircbotx.PircBotX.shutdown(PircBotX.java:2833)
        at org.pircbotx.InputThread.run(InputThread.java:115)
Caused by: java.lang.InterruptedException
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1301)
        at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:236)
        at org.pircbotx.Channel.getMode(Channel.java:127)
        ... 5 more

Leon Blakey

unread,
Jul 24, 2013, 6:59:22 PM7/24/13
to pirc...@googlegroups.com
Sorry for the delay. I have been busy lately with both life and other projects which limits the time I can volunteer for PircBotX.

First, in 2.0 you are not supposed to call shutdown(). With the rewrite it is an internal method and I simply forgot that it was still marked public. I just changed it to protected in Revision eed3b43b85b9 so it won't confuse people anymore

The proper way is to call sendIRC().quitServer() so PircBotX can send QUIT to the server. The server properly registers the QUIT, removes you from the channels, and closes the socket. Without sending QUIT most of the time your bot will still be on the server until a ping timeout around 240 seconds later (this was a real problem for me a while ago when testing since the nick was in use). With the latest 2.0-SNAPSHOT, this quits and exits the JVM as expected: http://pastebin.com/cm7i0gaz

Moving onto System.exit() you've managed to deadlock ThreadedListenerManager's shutdown since apparently System.exit() runs the shutdown threads. While this is a terrible untested way to shutdown the bot (its only slightly more graceful than kill -9), deadlocking the JVM isn't much better. Fixed with more checks in Revision ac75a6db2146.




--
You received this message because you are subscribed to the Google Groups "pircbotx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pircbotx+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Leon Blakey

unread,
Jul 24, 2013, 7:28:51 PM7/24/13
to pirc...@googlegroups.com
With exiting in 1.9, once again properly shutting down the bot with bot.quitServer() gives a clean disconnect. System.exit() seems to cause a SocketException when writing QUIT, most likely due to weird racing issues (shutdown() in 1.9 wasn't really protected from concurrent calls). However System.exit() is not the proper way to shutdown the bot and was untested.

With your exception I thought I had fixed that before releasing, but apparently not. Essentially 1.9 is trying to get the potential channel key so it can reconnect later. However that relies on the mode, which by default is fetched from the potentially disconnected server. There's so many racing issues with the 2 IO threads in 1.9 that its not easy to fix. I can tell you though that 2.0 does not have this problem: http://pastebin.com/chN1XXih

However, I will not be releasing a bugfix for 1.9 with the 2.0 release so (hopefully) close. 1.9 is also a mess when it comes to racing that I don't want to deal with anymore.

If you have any more questions or problems just let me know
Reply all
Reply to author
Forward
0 new messages