2

I've a very annoying problem and I'm not able to fix this by myself.

I have a simple JavaFX Scene with just 2 buttons for start and killing the thread. The stop-action is not relevant in this case because I'm not able to get the thread working well. The actionListener looks like:

EDIT1: Figured out the problem, it's not thread specific, it's the request against the TimeServer, take a look here: answer
Thanks to everyone of you who answered this or read the question! :)

private FarmAction action = null;

@FXML
void btnStartListener(ActionEvent event) {      
Firefox ff = new Firefox();
ff.startBrowser();

BrowserAction browserAction = new BrowserAction(ff.getDriver(), ff.getJse());
browserAction.loginToGame(user, pass);
ObservableList<AttackCommand> list = (ObservableList<AttackCommand>) Serializer.deserialize(Constants.FILE_NAME_TESTPURPOSE);


if(action == null)
    action = new FarmAction(ff.getDriver(), ff.getJse(), list);

Thread run = new Thread(action);
try {
    run.start();
} catch (Exception e) {
    e.printStackTrace();
} catch (Throwable t) {
    t.printStackTrace();
 }
}   

Note: I'm working with the Selenium Framework to automate some clicks on a Website.

My FarmAction class looks like this:

public class FarmAction implements Runnable{

private WebDriver driver;
private JavascriptExecutor jse;
private ObservableList<AttackCommand> attackList;
private boolean stop = false;

public FarmAction(WebDriver driver, JavascriptExecutor jse, ObservableList<AttackCommand> attackList) {
    this.driver = driver;
    this.jse = jse;
    for(AttackCommand ac : attackList)
    {
        ac.transferFromPropToAttributes();
    }
    this.attackList = attackList;
}


@Override
public void run() {
    ArrayList<Integer> unitIds = Constants.UNIT_ID_LIST_ALL;
    if(!driver.getCurrentUrl().equals(Constants.URL_TESTPURPOSE))
            driver.navigate().to(Constants.URL_TESTPURPOSE);
    int count = 0;
    while(true) { // Just let the Thread run for duration = lifetime of application
        System.out.println(count++); //count how often the thread runs into this while loop before terminating for no reason
        for(AttackCommand ac : attackList) {            
            for(int i = 0; i < unitIds.size(); i ++) {
                int unitKey = unitIds.get(i); // Momentane UnitID der Iteration                 
                if(ac.getUnits().containsKey(unitKey) && ( ac.getTurnBackTime() == 0 ||ac.getTurnBackTime() <= DateUtil.getActualServerTime())) // getActualServerTime is request against the timeserver de.pool.ntp.org
                {
                    String textfieldName = Constants.HASHMAP_TEXTFIELD_NAME_ALL_HTML_PLACE.get(unitKey);
                    WebElement textfield = driver.findElement(By.name(textfieldName));
                    textfield.sendKeys(String.valueOf(ac.getUnits().get(unitKey)));

                    WebElement textfieldCoordinates = driver.findElement(By.name(Constants.TEXTFIELD_NAME_HTML_PLACE_COODRINATESFORTARGET));
                    textfieldCoordinates.sendKeys(StringHelper.getPointAsString(new Point(ac.getXCoordinates(), ac.getYCoordinates())));


                    WebElement submitButton = driver.findElement(By.id(Constants.TA));
                    submitButton.click();

                    WebElement sndAttackSubmitButton = driver.findElement(By.name(Constants.SBM));

                    WebElement span = driver.findElement(By.className(Constants.CLASSNAME_TIME));
                    long duration = Long.parseLong(span.getAttribute(Constants.ATTRIBUTE_DURATION));

                    sndAttackSubmitButton.click();
                    ac.setStartTime(DateUtil.getActualServerTime());
                    ac.setDurationInSeconds(duration*1000);
                    ac.setTurnBackTime(ac.getStartTime()+ac.getDurationInSeconds());
                } 
            }
        }
    }
}}

As you see I've wrapped the Thread.start() method into a try-catch for Throwables AND Exceptions but I don't get any Stacktrace if the thread stops for no reason. I expected an StackOverFlow Error but I don't catch anything.

The amount of loops my thread is working is very different. Sometimes it stops after 12, then other times after 370 or 59. All values are examples - it's different each time.

Do you have any Ideas what I'm doing wrong?

Thanks in advance!

Community
  • 1
  • 1
  • 1
    Imagine if this worked... then `start` wouldn't be able to return until the thread finished (in order to know there were no exceptions) which would defeat the point of using threads! – user253751 May 28 '15 at 00:37
  • Can you check if the thread you created is a daemon thread? I guess (not verified yet) the event dispatch thread is actually daemon thread, which caused your thread created being daemon too. Your application just end gracefully for which the daemon threads are terminated by force, hence no special exception nor predictable number of loops – Adrian Shum May 28 '15 at 03:20
  • @immibis are you sure? the point of using thread is, a separate thread is spawned to execute the `run()` of the provided `Runnable`. `start()` simply start that execution thread and return right away – Adrian Shum May 28 '15 at 03:22
  • @AdrianShum Well, `start()` can't possibly throw an exception after it returns. (I was talking about a *hypothetical* situation where if `run` terminated by throwing an exception, that exception would then propagate to the caller of `start`) – user253751 May 28 '15 at 03:37
  • @immibis oops! got your point here :) You are exactly right :) – Adrian Shum May 28 '15 at 03:38
  • i tried thread.isDeamon(); out, the result is false, so it's not a deamon thread. – user3573426 May 28 '15 at 10:16
  • just wonder... are you sure that you are looking at the correct place for std out and std err? – Adrian Shum May 28 '15 at 10:17

4 Answers4

1

You need to check for exceptions inside the run() method of the Thread class.

After calling the start() method, the thread created has its own stack, which is different to the stack of the main thread, where the start() method is called from.

Therefore, exceptions thrown inside the run() method of the thread, will not be visible to the catch statements related to the start() method.

PNS
  • 19,295
  • 32
  • 96
  • 143
  • Thanks for your answer! I wrapped the whole while loop between a try-catch block as well but still there's no Exception, no Throwable. Also there are no exceptions or throwables if FarmAction extends Thread itself with try-catched while loop. – user3573426 May 28 '15 at 00:40
  • Try isolating the issue. For example, put print statements before every command in the loop. – PNS May 28 '15 at 02:37
1

As mentioned by @Immibis in the comment, there is no meaning catching exception around thread.start() as it will return right-away.

One way to inspect the exception is to make use of the UncaughtExceptionHandler, which looks like this:

Thread run = new Thread(action);
run.setUncaughtExceptionHandler(
    new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            e.printStackTrace();
        }
    }
);
run.start();
Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
  • Thanks for this, I tried this snippet but still got no stacktrace – user3573426 May 28 '15 at 10:12
  • Have you checked my another suggestion in comment? If even the uncaught handler is not giving any error, it can be possible that the thread is simply stopped by force, which the only possibly I can think of is daemon thread ending when app stop – Adrian Shum May 28 '15 at 10:16
  • Yes, I've checked the output from thread.isDaemon(). It was **false**. I also tried it with different priorities from 1 - 10 – user3573426 May 28 '15 at 11:04
  • Figured it out, look here: [answer](http://stackoverflow.com/questions/30495114/java-thread-stops-without-exception-throwable/30506720#30506720) – user3573426 May 28 '15 at 12:33
1

OK guys, I've figuered the problem out. It's not thread specific, sorry for that, but I've learned almost a bit more about threads because of your answers :) Thanks to everyone of you!

I've put SystemOuts behind every single codeline and figured out after 25 runs and freezes there are two possible codelines where thread stops working:

Both statements use my DateUtil.getActualServerTime() Method which looks as follows: ​

public static long getActualServerTime() {
    String TIME_SERVER = "de.pool.ntp.org";   
    NTPUDPClient timeClient = new NTPUDPClient();
    InetAddress inetAddress;
    long returnTime = 0;

    try {
        inetAddress = InetAddress.getByName(TIME_SERVER);
        TimeInfo timeInfo = timeClient.getTime(inetAddress);
        returnTime = timeInfo.getMessage().getTransmitTimeStamp().getTime();
    } catch (Exception e) {
        e.printStackTrace();
    } catch (Throwable t) {
        t.printStackTrace();
    }

    return returnTime;
}

I'm using the apache.commons.net lib for that. If I'm just return a Date d = new Date(); return d.getTime(); my thread works fine for about 60.000 loops until I've stopped it manually.

I don't get an Exception or Throwable here as well. I'd say theres a maximum amount of request against the time server in a specific time or something like that. I can't figure it out on the Website right now.

Fabian N.
  • 3,807
  • 2
  • 23
  • 46
  • 1
    I'm having this problem now (stopping without exception) and it's happening about 2% of the time when calling NTPUDPClient's getTime method. The method hangs and doesn't return anything. Were you able to determine a solution? – ScottyB Jun 18 '16 at 16:05
  • After looking around, I'm pretty sure I found the solution. The getTime method will wait forever and not throw an exception unless you set a timeout on the NTPUDPClient instance. (e.g., client.setDefaultTimeout(5000); for 5 seconds) I saw it throw the exception and continue. – ScottyB Jun 18 '16 at 16:29
0

I have same problem too,my thread is terminated without any exception/throwable.

I have a thread for accept socket (nio, but blocking-mode).that is works well, if socket get receiving requests by slow speed,but when receiving a lot of requests at a time ,the thread stops.

I changed a few options in linux, like mem [net.ipv4.tcp_rmem, net.core.wmem_default, net.ipv4.tcp_mem], may be for this?

Ali Bagheri
  • 3,068
  • 27
  • 28