Create account / Log in

Hang on exit from GTS modules

Discussion area for the development team.

Moderators: Tim M, uckelman

Hang on exit from GTS modules

Postby Brent Easton » January 13th, 2013, 9:53 pm

Hi Joel,

I have a problem with my GTS modules containing my custom Devil's Cauldron code. The modules are hanging on exit in ZipArchive.revert() at the w.lock() statement. This is being called during the DataAtchive.close() call.

It only happens if you instantiate one of the counters that includes my custom code. I can't see it, any ideas?

To reproduce - Open the No Question Of Surrender module with 3.2.2. Start a new Scenario 1. Open the counter palette, Units - French and drag any french counter on to the map. Quit the game.

The source for the custom code is all in VSQL/tdc.

thanks,
Brent.
User avatar
Brent Easton
 
Posts: 2757
Joined: December 21st, 2007, 3:06 am
Location: Berry, NSW, Australia

Re: Hang on exit from GTS modules

Postby uckelman » January 15th, 2013, 10:43 pm

Thus spake Brent Easton:
> Hi Joel,
>
> I have a problem with my GTS modules containing my custom Devil's
> Cauldron code. The modules are hanging on exit in ZipArchive.revert() at
> the w.lock() statement. This is being called during the
> DataAtchive.close() call.
>
> It only happens if you instantiate one of the counters that includes my
> custom code. I can't see it, any ideas?

This sounds like a stream is being left open. I fixed a problem lik
this in VASL just before Christmas. I'll try to look at it sometime in
the next few days, now that I have internet at home once again.

--
J.
User avatar
uckelman
Site Admin
 
Posts: 8137
Joined: December 10th, 2007, 9:48 am
Location: Durham, England

Re: Hang on exit from GTS modules

Postby uckelman » February 17th, 2013, 8:36 pm

Thus spake Brent Easton:
> Hi Joel,
>
> I have a problem with my GTS modules containing my custom Devil's
> Cauldron code. The modules are hanging on exit in ZipArchive.revert() at
> the w.lock() statement. This is being called during the
> DataAtchive.close() call.
>
> It only happens if you instantiate one of the counters that includes my
> custom code. I can't see it, any ideas?

The problem isn't in the tdc package, it's in the terrain package. Here's
the stack trace in which there's an input stream which is created, but
not closed:

java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Thread.java:1342)
at VASSAL.tools.io.ZipArchive$ZipArchiveInputStream.(ZipArchive.java:632)
at VASSAL.tools.io.ZipArchive.getInputStream(ZipArchive.java:222)
at VASSAL.tools.DataArchive.getInputStreamImpl(DataArchive.java:247)
at VASSAL.tools.DataArchive.getInputStream(DataArchive.java:207)
at VASSAL.tools.DataArchive.getFileStream(DataArchive.java:760)
at terrain.TerrainMap.load(TerrainMap.java:326)
at terrain.TerrainMap.(TerrainMap.java:73)
at terrain.TerrainDefinitions.getTerrainMap(TerrainDefinitions.java:69)
at terrain.TerrainHexGrid.getTerrainMap(TerrainHexGrid.java:75)
at terrain.TerrainHexGrid.getTerrainName(TerrainHexGrid.java:63)
at tdc.TdcMap.getTerrainProperty(TdcMap.java:89)
at tdc.UnitInfo.findBasicInfo(UnitInfo.java:381)
at tdc.UnitInfo.(UnitInfo.java:159)
at tdc.TdcHighlighter.draw(TdcHighlighter.java:65)
at VASSAL.build.module.map.StackMetrics.draw(StackMetrics.java:355)
at VASSAL.build.module.Map.drawPiecesInRegion(Map.java:1510)
at VASSAL.build.module.Map.paintRegion(Map.java:1478)
at VASSAL.build.module.Map.paintRegion(Map.java:1471)
at VASSAL.build.module.Map$View.paint(Map.java:2591)
at javax.swing.JComponent.paintChildren(JComponent.java:878)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JViewport.paint(JViewport.java:731)
at javax.swing.JComponent.paintChildren(JComponent.java:878)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JComponent.paintChildren(JComponent.java:878)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:585)
at javax.swing.JComponent.paintChildren(JComponent.java:878)
at javax.swing.JSplitPane.paintChildren(JSplitPane.java:1047)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JComponent.paintChildren(JComponent.java:878)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JComponent.paintChildren(JComponent.java:878)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:585)
at javax.swing.JComponent.paintChildren(JComponent.java:878)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5212)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:295)
at javax.swing.RepaintManager.paint(RepaintManager.java:1236)
at javax.swing.JComponent._paintImmediately(JComponent.java:5160)
at javax.swing.JComponent.paintImmediately(JComponent.java:4971)
at javax.swing.RepaintManager$3.run(RepaintManager.java:796)
at javax.swing.RepaintManager$3.run(RepaintManager.java:784)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:784)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:757)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:706)
at javax.swing.RepaintManager.access$1000(RepaintManager.java:62)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1651)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:727)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:688)
at java.awt.EventQueue$3.run(EventQueue.java:686)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:697)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)

(How I found this: I changed ZipArchiveInputStream so that its ctor
prints "this" and a stack trace, and its close() method prints "this".
Then, I looked for the ZAIS which showed up only once in the log. That's
the one which isn't being closed properly.)

The line numbers for TerrainMap seem to be off a bit from what's in
the repo now; the bug is here:

public void load() {
try {
final DataArchive archive = GameModule.getGameModule().getDataArchive();
final InputStream stream = archive.getFileStream(getMapFileName(board));
final InputStreamReader reader = new InputStreamReader(stream, CHAR_SET);
final BufferedReader buffer = new BufferedReader(reader);
for (String line = buffer.readLine(); line != null; line = buffer.readLine()) {
if (line.startsWith(TerrainHex.TYPE)) {
addHexTerrain(line);
}
else if (line.startsWith(TerrainEdge.TYPE)) {
addEdgeTerrain(line);
}
else if (line.startsWith(TerrainLine.TYPE)) {
addLineTerrain(line);
}
else if (line.startsWith(TerrainAttribute.TYPE)) {
addAttributeTerrain(line);
}
}
}
catch (Exception e) {

}
}

What you need is to make sure the stream is closed, no matter what
else happens:

public void load() {
try {
final DataArchive archive = GameModule.getGameModule().getDataArchive();

InputStream stream = null;
try {
stream = archive.getFileStream(getMapFileName(board));

final InputStreamReader reader = new InputStreamReader(stream, CHAR_SET);
final BufferedReader buffer = new BufferedReader(reader);
for (String line = buffer.readLine(); line != null; line = buffer.readLine()) {
if (line.startsWith(TerrainHex.TYPE)) {
addHexTerrain(line);
}
else if (line.startsWith(TerrainEdge.TYPE)) {
addEdgeTerrain(line);
}
else if (line.startsWith(TerrainLine.TYPE)) {
addLineTerrain(line);
}
else if (line.startsWith(TerrainAttribute.TYPE)) {
addAttributeTerrain(line);
}
}
}
finally {
IOUtils.closeQuietly(stream);
}
}
catch (Exception e) {

}
}

This was the only unclosed stream I saw, so I suspect this will be
sufficient to solve the problem.

--
J.
User avatar
uckelman
Site Admin
 
Posts: 8137
Joined: December 10th, 2007, 9:48 am
Location: Durham, England

Re: Hang on exit from GTS modules

Postby Brent Easton » February 17th, 2013, 10:27 pm

Fantastic,

Thanks Joel, I will get that sorted out.

Brent.

On 18/02/2013 7:36 AM, Joel Uckelman wrote:
> Thus spake Brent Easton:
>> Hi Joel,
>>
>> I have a problem with my GTS modules containing my custom Devil's
>> Cauldron code. The modules are hanging on exit in ZipArchive.revert() at
>> the w.lock() statement. This is being called during the
>> DataAtchive.close() call.
>>
>> It only happens if you instantiate one of the counters that includes my
>> custom code. I can't see it, any ideas?
> The problem isn't in the tdc package, it's in the terrain package. Here's
> the stack trace in which there's an input stream which is created, but
> not closed:
>

--
____________________________________________________________
Brent Easton
Analyst/Programmer
University of Western Sydney
Email: b.easton@exemail.com.au
User avatar
Brent Easton
 
Posts: 2757
Joined: December 21st, 2007, 3:06 am
Location: Berry, NSW, Australia


Return to Developers

Who is online

Users browsing this forum: No registered users and 0 guests