StokeBloke.com

Hang in Java FileSystemView getFileSystemView() getSystemIcon()

Wednesday, March 18th, 2009

Recently I was working on a deadlock in our startup code.

It took some time to track it down as it never appeared as a deadlock (via CTRL-Break) it just stopped running with 0 CPU usage.

The cause was

 FileSystemView.getFileSystemView().getSystemIcon(file)

It appears that this call fails when called from multiple threads asking for the same system icon.

Below is an example on how to show the issue. Its was tested with Java 1.6.0_07

    public void testGetSystemIcon() throws IOException,
                                           InterruptedException {
        final FileImageThread t1 = new FileImageThread(".jpg");
        final FileImageThread t2 = new FileImageThread(".jpg");
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }

    public class FileImageThread extends Thread {
        final File file;

        public FileImageThread(final String suffix) throws IOException {
            file = File.createTempFile("test", suffix);
        }

        @Override
        public void run() {
            FileSystemView.getFileSystemView().getSystemIcon(file);
        }
    }

It does not hang every time, but it happens enough to be an issue.

The hang call stack is

Thread  id=22 name=Thread-4 inState=WAITING deadlocked=false isNative=false
  sun.misc.Unsafe.park(Native Method)
  java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
  java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:747)
  java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:905)
  java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1217)
  java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:218)
  java.util.concurrent.FutureTask.get(FutureTask.java:83)
  sun.awt.shell.Win32ShellFolderManager2$ComInvoker.invoke(Win32ShellFolderManager2.java:495)
  sun.awt.shell.Win32ShellFolder2.(Win32ShellFolder2.java:225)
  sun.awt.shell.Win32ShellFolderManager2.getDrives(Win32ShellFolderManager2.java:101)
  sun.awt.shell.Win32ShellFolderManager2.isFileSystemRoot(Win32ShellFolderManager2.java:323)
  sun.awt.shell.ShellFolder.isFileSystemRoot(ShellFolder.java:234)
  javax.swing.filechooser.FileSystemView.isFileSystemRoot(FileSystemView.java:310)
  com.osm.ui.FileImageUtilsTest$FileImageThread.run(FileImageUtilsTest.java:62)

Thread  id=21 name=Thread-3 inState=WAITING deadlocked=false isNative=false
  sun.misc.Unsafe.park(Native Method)
  java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
  java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:747)
  java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:905)
  java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1217)
  java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:218)
  java.util.concurrent.FutureTask.get(FutureTask.java:83)
  sun.awt.shell.Win32ShellFolderManager2$ComInvoker.invoke(Win32ShellFolderManager2.java:495)
  sun.awt.shell.Win32ShellFolder2.(Win32ShellFolder2.java:225)
  sun.awt.shell.Win32ShellFolderManager2.getDrives(Win32ShellFolderManager2.java:101)
  sun.awt.shell.Win32ShellFolderManager2.isFileSystemRoot(Win32ShellFolderManager2.java:323)
  sun.awt.shell.ShellFolder.isFileSystemRoot(ShellFolder.java:234)
  javax.swing.filechooser.FileSystemView.isFileSystemRoot(FileSystemView.java:310)
  com.osm.ui.FileImageUtilsTest$FileImageThread.run(FileImageUtilsTest.java:62)

No one else seemed to see this issue, but I saw it lots of times on my PC.

Python timing decorator

Tuesday, January 27th, 2009

I have been using python as my main scripting language for some time, but recently I wanted to profile some of my scripts to see why it was taking so long.

I looked at the python profiler but I keep looking for some reason.

Finally I found this code snippet (I don’t remember from where, maybe here one night at mccool s online )

You can use python @ decorator to wrap functions with timing metrics.

def print_timing(func):
  def wrapper(*arg):
    t1 = time.time()
    res = func(*arg)
    t2 = time.time()
    print '%s took %0.3f ms' % (func.func_name, (t2-t1)*1000.0)
    return res
  return wrapper

Then simply use like this

@print_timing
def some_func(n):
    //do work

This allows lots of control as you can put metrics on 1 or more functions.

Java Runtime and cmd.exe unicode issue

Thursday, November 13th, 2008

For many years our product used the following code to open URLs or files on Windows 2000 and XP.

final String[] cmds = { "cmd.exe", "/C", "start", "/B ", "/WAIT", url };
Runtime.getRuntime().exec(cmds);

This code is really simply and works well. If you have different editors configured for a specific file type the start launches the correct viewer/editor. It also opens the users preferred web browser too.

We didn’t have many issues with this until we started added more localisations to our product and supporting unicode fully.

This code in theory looks good, but it didn’t work in many cases. I found that the cmd.exe process on a European Windows system runs in ISO-8859-1 so any arguments we passed it get completely messed up.

This means the cmd.exe cannot be used as it doesn’t support unicode.

I spent days looking for another alternative but couldnt find a java only fix.  In the end we had to use JNI and use the Windows ShellExecuteExW and ShellExecuteEx calls (based on whether we used a unicode or none unicode string)

Cygwin .Xresources for rxvt.

Thursday, September 18th, 2008

I dont actually like the default colors for rxvt.   So I thought there may be more people who dont like it either.

Here is my .Xresources I use for my cygwin rxvt executable.

rxvt.font:            Lucida Console-14
rxvt.scrollBar:       True
rxvt.scrollBar_right: True
rxvt.visualBell:      True
rxvt.loginShell:      True
rxvt.geometry:        140x25
rxvt.background:      Black
rxvt.foreground:      White
rxvt.cursorColor:     Green
rxvt.cursorColor1:    Pink
rxvt.colorBD:         Red
rxvt.colorUL:         Yellow
rxvt.saveLines:       200

! My custom colors
rxvt*color0:    #000000
rxvt*color1:    #FF2020
rxvt*color2:    #20FF20
rxvt*color3:    #FFFF00
rxvt*color4:    #4040FF
rxvt*color5:    #A800A8
rxvt*color6:    #00A8A8
rxvt*color7:    #D8D8D8
rxvt*color8:    #000000
rxvt*color9:    #FF2020
rxvt*color10:   #20FF20
rxvt*color11:   #FFFF00
rxvt*color12:   #4040FF
rxvt*color13:   #A800A8
rxvt*color14:   #00A8A8
rxvt*color15:   #D8D8D8

This is what it looks like

Cygwin Custom Colors persuasion movie

Using subversion from behind a proxy (HTTPS)

Tuesday, September 2nd, 2008

Subversion can be used from behind a proxy quiet easily.

Go to either (Windows)

sideways online download %APPDATA%\Subversion

or (Linux)

~/.subversion

watch nomad online and edit the servers file.

You need to have a entry like this in the file.

[global]
http-proxy-host = someproxy.name.com
http-proxy-port = 9999

Now you can connect out to external subversion servers.
You may need to read about (and set) the http-proxy-exceptions variable if you have internal and external servers.

There is also a

  • http-proxy-password
  • http-proxy-username

variable which may need to be set if your proxy requires authentication.