Hang on exit from GTS modules

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.

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.

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.

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