1

I am writing a program in Java that uses a DDS mechanism for messaging that starts its own background threads when writers and the such are created. However if in the main thread an error occurs I throw an exception with the following code.

throw new FooUncheckedException(writerTypes.get(i) + " is not a writer type");

The main thread then terminates like it is supposed to. However, the background threads created by the DDS library I am using continue to run so the program never stops running technically. How would I go about gracefully shutting down the background threads as well that are keeping the program alive?

jgr208
  • 2,896
  • 9
  • 36
  • 64
  • you need to have a notification setup so you can kill those threads too. – StackFlowed Feb 26 '15 at 19:00
  • @StackFlowed the code to those threads created by the library i am using is not open source however, so unable to be modified. – jgr208 Feb 26 '15 at 19:02
  • When you spawn new threads you need to add a reference to the notification class which will in turn kill them when needed. – StackFlowed Feb 26 '15 at 19:04
  • generally a background thread has an activity loop that checks at the top of its iteration to see if it should no longer continue. this can be a flag that's set by a simple boolean API, or could be that its work queue is empty, or... so before looking into `kill` type methods, see if that particular library has something to offer. – BaseZen Feb 26 '15 at 19:04
  • @BaseZen I did not see anything so far from your first part of the suggestion but am still digging as deep as I can into the API to try and find something. But it seems like I may just have to kill them, which I know to avoid at all cost due to other side effects that might happen from suddenly stopping a thread. – jgr208 Feb 26 '15 at 19:06
  • Been a while since I read Sun's treatise on this, but Thread.stop is actually deprecated if not fully phased out: http://stackoverflow.com/questions/671049/how-do-you-kill-a-thread-in-java If the code is poorly written to not handle error conditions, and is closed source...I mean...bad is bad. I see 3 awkward ways forward A) Social engineering (psst! tell me about your closed source, and fix it too!) B: reverse engineering (decompilation tool, which may violate a license) III. Back out to the system level have a control script kill & restart the VM. I did say _awkward_. – BaseZen Feb 26 '15 at 19:10
  • Does that library allow you to create daemon threads instead of user threads? – spudone Feb 26 '15 at 19:14
  • @spudone it is not me creating the threads, it is the library creating them in the background when a DDS writer is made. So it lives on its own thread – jgr208 Feb 26 '15 at 19:15
  • Please provide a link to the library and I can take a look. – spudone Feb 26 '15 at 19:17
  • @spudone http://www.rti.com/products/dds/ and the api is http://community.rti.com/rti-doc/510/ndds/doc/html/api_java/index.html – jgr208 Feb 26 '15 at 19:19
  • Ah, you're interacting with a higher level library than I imagined. Probably time to put in some source code to check against the API. Generally I see a lot of mentions of deleting things, e.g: `DDSDomainParticipant::delete_topic` Perhaps when the all resources are explicitly released, the library will stop the threads it's using to handle them. – BaseZen Feb 26 '15 at 19:25
  • Are you tearing down the datawriter(s) when your main thread exits? Bottom of this page: http://community.rti.com/rti-doc/510/ndds/doc/html/api_java/group__DDSWriterExampleModule.html#details – spudone Feb 26 '15 at 19:25
  • @spudone no i am not since i only looked at the api calls really before and didnt think about using that, also we wanted our writers to never be torn down since that would only happen when our system crashes which is why i also missed that detail. I will try that but might have to rework my design a little then to implement this correctly for tearing down the writers. – jgr208 Feb 26 '15 at 19:31
  • @spudone did `publisher.delete_datawriter(writer); participant.delete_publisher(publisher); participant.delete_topic(topic); DomainParticipantFactory.TheParticipantFactory.delete_participant(participant);` and no impact at all – jgr208 Feb 26 '15 at 20:29
  • @BaseZen i tried this and however it didnt appear to have any effect. – jgr208 Feb 26 '15 at 21:02
  • The API docs cover 6 or so essential threads that the library runs. I would be curious which ones are still running after you've released everything you can: http://stackoverflow.com/questions/1323408/get-a-list-of-all-threads-currently-running-in-java – BaseZen Feb 26 '15 at 22:56
  • Are the 15 comments on this question really asking for clarifications, as comments should? OP, please edit additional information into the question (instead of comments) so we don't have to sift through the comments. Answerers, please write an answer that can be voted and commented upon. – meriton Feb 26 '15 at 22:57
  • Did you do the actions as included in the `finally` block in [this example code](http://community.rti.com/rti-doc/510/ndds/doc/html/api_java/HelloWorldPublisher_8java-example.html), for tearing down the participant? – Reinier Torenbeek Feb 27 '15 at 03:40
  • @BaseZen figured it out. It was participant.delete_contained_entities() – jgr208 Mar 02 '15 at 13:31
  • @ReinierTorenbeek i did but i didnt use the participant.delete_contained_entities(); now that i did works like a charm thanks for the help! – jgr208 Mar 02 '15 at 13:31

4 Answers4

2

Before exiting the main thread, I would try cleaning up like this:

participant.delete_contained_entities(); 
DomainParticipantFactory.get_instance().delete_participant(participant);

[repeat for each participant you may have created...]

That should reclaim any resources (including threads) held/created by the participant.

C Tucker
  • 301
  • 1
  • 8
1

What implementation of DDS are you using? If the DDS implementation you are using is implemented in native code, which is pretty typical, then the background threads created by the DDS library are native threads and you would not be able to make Java calls things like "setDaemon()" on them...

The mechanism described by C Tucker above is the standard DDS API to release all resources that the DDS middleware library creates for a given DomainParticipant so this should, among other things, terminate any internal threads the DDS implementation started. If it is not doing it I would consider is a bug in that particular DDS implementation.

Gerardo

Gerardo Pardo
  • 1,001
  • 8
  • 5
  • am using RTI and yes you are correct about that. that was the problem i was having trouble with when trying to delete them, since they are created in native code and can't really be handled in java gracefully without knowing the API calls to use from the DDS library. – jgr208 Mar 02 '15 at 13:34
0

If you set the daemon flag on the background threads before starting them, then they will be automatically killed when your main thread exits.

Thread t = new Thread(...);
t.setDaemon(true);
t.start();

A Java Virtual Machine will shut down and exit as soon as the last non-daemon thread dies. When your program first starts up, the main() thread is the only non-daemon thread.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
0

"gracefully shutting down the background threads" will require the cooperation of those threads, i.e. they must provide some kind of API to request a shut down.

If it is ok to kill these threads instantly (without giving them the opportunity to finish what they are currently doing), and you want to terminate execution of the entire program, System.exit() may be the best choice. If you want to do this whenever an unhandled exception occurs, you can catch the exception in your main method:

try {
    doSomethingThatMightThrowAnException();
} catch (Throwable t) {
    reportError(t);
    System.exit();
}
meriton
  • 68,356
  • 14
  • 108
  • 175