Mint Talk in COMP 600

February 8th, 2010, 3:39 pm by Mathias

I just gave the first presentation about Mint in the COMP 600 graduate seminar at Rice. The slides for “Mint: A Multi-stage Extension of Java” are available (PowerPoint, PDF, view embedded). This weekend, I was kicking myself why I had volunteered for this talk out of turn, but it was good practice, and I’m a philanthropist and got the other grad students pizza that way.

Thanks for the opportunity to speak and for the good feedback!

Finally, the Java Mint Blog has a new URL: www.javamint.org. We currently also have some problems with the implementation URL; for now, you can use http://mint.concutest.org as a resource hub for everything Mint-related.

Print This Print This   Email This Email This

Presentation: Mint: A Multi-stage Extension of Java

February 8th, 2010, 3:27 pm by Mathias

Mint: A Multi-stage Extension of Java
(PowerPoint, PDF, view embedded)

Where: Rice University Computer Science Department, COMP 600 Graduate Seminar
When: February 8, 2010

Multi-stage programming (MSP) provides a safe way of generating code at run-time. In mostly-functional languages like MetaOCaml, this has been used to reduce the performance penalties of abstractions such as loops, recursion or interpretation. The main advantage of MSP compared to other techniques, such as string or LISP quotations, is that MSP guarantees type safety for the generated code statically, at the time the program is compiled.

Unfortunately, MSP is difficult to combine with imperative features found in most mainstream languages like Java. The central problem is “scope extrusion”, which may accidentally move variables outside the scopes in which they are bound, leading to run-time errors in the generated code. This problem can be prevented if code in escapes (or “anti-quotes”) is “weakly separable”, i.e. the computational effects occurring inside an escape that are visible from the outside do not involve code.

We have formalized a type system, based on Lightweight Java, that uses weak separability to prevent scope extrusion, and we have proved that the type system is sound. We have also developed an implementation called Mint to demonstrate the expressivity of the type system and the performance benefits MSP can provide in an imperative setting. Since our implementation extends the Java language, our work is accessible to mainstream programmers.

This talk is based on work done in collaboration with Edwin Westbrook, Jun Inoue, Yilong Yao, Tamer Abdelatif, and Walid Taha. A paper titled “Mint: Java Multi-stage Programming Using Weak Separability” has been accepted for publication in the Proceedings of the 2010 ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI 2010).

Print This Print This   Email This Email This

Paper: Mint: Java Multi-stage Programming Using Weak Separability

January 31st, 2010, 8:21 pm by Mathias

Mint: Java Multi-stage Programming Using Weak Separability

2010 ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI 2010)

Multi-stage programming (MSP) provides a disciplined approach to run-time code generation. In the purely functional setting, it has been shown how MSP can be used to reduce the overhead of abstractions, allowing clean, maintainable code without paying performance penalties. Unfortunately, MSP is difficult to combine with imperative features, which are prevalent in mainstream languages. The central difficulty is scope extrusion, wherein free variables can inadvertently be moved outside the scopes of their binders. This paper proposes a new approach to combining MSP with imperative features that occupies a “sweet spot” in the design space in terms of how well useful MSP applications can be expressed and how easy it is for programmers to understand. The key insight is that escapes (or “anti-quotes”) must be weakly separable from the rest of the code, i.e. the computational effects occurring inside an escape that are visible outside the escape are guaranteed to not contain code. To demonstrate the feasibility of this approach, we formalize a type system based on Lightweight Java which we prove sound, and we also provide an implementation, called Mint, to validate both the expressivity of the system and the performance gains attainable by using MSP in this setting.

Print This Print This   Email This Email This

Java Bug 4396719 Work-Around?

January 31st, 2010, 12:00 pm by Mathias

It seems like I can get around the garbage collector bug if I use -XX:+UseConcMarkSweepGC JVM argument.

Now I’m having more Soot problems, but they actually make sense. In addition to being cross-platform, DrJava is also “cross-JDK version”: We support JDK versions 5 and 6 and OpenJDK version 6. In the past, we also supported JDK version 4 and various versions of JSR-14 (adding generics to Java 4).

The adapter to the JDK 5 compiler is compiled with and linked against JDK 5; the adapter to the JDK 6 compiler is compiled with and linked against JDK 6. At runtime, we will never use a JDK 5 adapter with a JDK 6 compiler, and vice versa. But when I’m generating the call graph with JDK 6, Soot is now also looking at the JDK 5 adapter.

The JDK 5 com.sun.tools.javac.util.Log class had a String getText(String a, Object[] b) method, but that has disappeared in JDK 6. Therefore, Soot is not finding a method it expects.

I guess I will have to remove the cross-version capability for the purpose of the call graph creation.

Update

On Windows and Mac, using -XX:+UseConcMarkSweepGC actually seems to help. On Linux, I’m still getting a segfault.

Print This Print This   Email This Email This

Soot Build Instructions

January 30th, 2010, 7:39 pm by Mathias

While trying to create a call graph of DrJava using Soot, I ran into some problems that were supposed to have been fixed in the Soot nightly builds already. Unfortunately, the nightly builds I could find were all many months old. So I built Soot from scratch from the Subversion repository, which wasn’t an easy task.

Here are some instructions for building Soot:

  1. Make sure you have Ant ant the JDK (5 or newer) installed.
  2. Check out and download all of these code bases in the same directory.
  3. Download Polyglot from http://www.sable.mcgill.ca/soot/soot_download.html:
    wget http://www.sable.mcgill.ca/software/polyglotclasses-1.3.5.jar
  4. Check out Soot from https://svn.sable.mcgill.ca/soot/soot/trunk:
    svn checkout https://svn.sable.mcgill.ca/soot/soot/trunk soot-dev
  5. Check out Jasmin from https://svn.sable.mcgill.ca/soot/jasmin/trunk:
    svn checkout https://svn.sable.mcgill.ca/soot/jasmin/trunk jasmin-dev
  6. Check out JastAddJ from http://svn.jastadd.org/projects/trunk/JastAddJ:
    svn co http://svn.jastadd.org/projects/trunk/JastAddJ
  7. Check out JastAddExtensions from http://svn.jastadd.org/projects/trunk/JastAddExtensions:
    svn co http://svn.jastadd.org/projects/trunk/JastAddExtensions
  8. You should now have the following directory structure:
    .
    |-- polyglotclasses-1.3.5.jar
    |-- JastAddExtensions
    |   |-- ...
    |   |-- SootJastAddJ
    |   `-- ...
    |-- JastAddJ
    |   `-- ...
    |-- jasmin-dev
    |   |-- ...
    |   |-- lib
    |   |   `...
    |   |-- ant.settings.template
    |   |-- build.xml
    |   `-- ...
    `-- soot-dev
        |-- ...
        |-- lib
        |   `...
        |-- ant.settings.template
        |-- build.xml
        `-- ...
  9. Copy jasmin-dev/ant.settings.template to jasmin-dev/ant.settings:
    cp jasmin-dev/ant.settings.template jasmin-dev/ant.settings
  10. Edit jasmin-dev/ant.settings so it contains the following lines:
    java_cup.jar=../polyglotclasses-1.3.5.jar
    jasmin.version=trunk
  11. Change into the jasmin-dev directory, build the jasminclasses-trunk.jar file, and change back out of the directory:
    cd jasmin-dev
    ant jasmin-jar
    cd ..
  12. The freshly built Jasmin jar file is jasmin-dev/lib/jasminclasses-trunk.jar.
  13. Change into the JastAddExtensions/SootJastAddJ directory, regenerate the JastAdd-generated files for Soot, and change back out of the directory:
    cd JastAddExtensions/SootJastAddJ
    ant gen
    cd ../..
  14. Copy soot-dev/ant.settings.template to soot-dev/ant.settings:
    cp soot-dev/ant.settings.template soot-dev/ant.settings
  15. Edit soot-dev/ant.settings so it contains the following lines:
    jastaddfrontend.loc=../JastAddExtensions/SootJastAddJ
    polyglot.jar=../polyglotclasses-1.3.5.jar
    jasmin.jar=../jasmin-dev/lib/jasminclasses-trunk.jar
  16. Change into the soot-dev directory and build the sootclasses-trunk.jar file, and change back out of the directory:
    cd soot-dev
    ant classesjar
    cd ..
    Note: I received a compiler error here. I had to insert the second cast into soot-dev/src/soot/jbco/bafTransformations/FindDuplicateSequences.java to make line 282
    1. Unit jump = (Unit) units.getSuccOf(next.get(next.size() - 1));
  17. read
    1. Unit jump = (Unit) units.getSuccOf((Unit)(next.get(next.size() - 1)));
  18. The freshly built Soot jar file is soot-dev/lib/sootclasses-trunk.jar.

Have fun with fresh Soot.

Here’s a bash script that does it all (except insert the cast): build-soot.sh.zip

  1. #!/bin/bash
  2.  
  3. # Make sure you have Ant ant the JDK (5 or newer) installed.
  4. # Check out and download all of these code bases in the same directory.
  5. # Download Polyglot from http://www.sable.mcgill.ca/soot/soot_download.html:
  6. wget http://www.sable.mcgill.ca/software/polyglotclasses-1.3.5.jar
  7.  
  8. # Check out Soot from https://svn.sable.mcgill.ca/soot/soot/trunk:
  9. svn checkout https://svn.sable.mcgill.ca/soot/soot/trunk soot-dev
  10.  
  11. # Check out Jasmin from https://svn.sable.mcgill.ca/soot/jasmin/trunk:
  12. svn checkout https://svn.sable.mcgill.ca/soot/jasmin/trunk jasmin-dev
  13.  
  14. # Check out JastAddJ from http://svn.jastadd.org/projects/trunk/JastAddJ:
  15. svn co http://svn.jastadd.org/projects/trunk/JastAddJ
  16.  
  17. # Check out JastAddExtensions from
  18. # http://svn.jastadd.org/projects/trunk/JastAddExtensions:
  19. svn co http://svn.jastadd.org/projects/trunk/JastAddExtensions
  20.  
  21. # Copy jasmin-dev/ant.settings.template to jasmin-dev/ant.settings:
  22. # Edit jasmin-dev/ant.settings so it contains the following lines:
  23. # java_cup.jar=../polyglotclasses-1.3.5.jar
  24. # jasmin.version=trunk
  25. cat jasmin-dev/ant.settings.template | sed \
  26. -e "s/.*\(java_cup.jar=\).*/3..\/polyglotclasses-1.3.5.jar/" \
  27. -e "s/.*\(jasmin.version=\).*/3trunk/" \
  28. > jasmin-dev/ant.settings
  29.  
  30. # Change into the jasmin-dev directory, build the
  31. # jasminclasses-trunk.jar file, and change back out of the directory:
  32. cd jasmin-dev
  33. ant jasmin-jar
  34. cd ..
  35.  
  36. # The freshly built Jasmin jar file is
  37. # jasmin-dev/lib/jasminclasses-trunk.jar. Change into the
  38. # JastAddExtensions/SootJastAddJ directory, regenerate the
  39. # JastAdd-generated files for Soot, and change back out of the
  40. # directory:
  41. cd JastAddExtensions/SootJastAddJ
  42. ant gen
  43. cd ../..
  44.  
  45. # Copy soot-dev/ant.settings.template to soot-dev/ant.settings:
  46. # Edit soot-dev/ant.settings so it contains the following lines:
  47. # jastaddfrontend.loc=../JastAddExtensions/SootJastAddJ
  48. # polyglot.jar=../polyglotclasses-1.3.5.jar
  49. # jasmin.jar=../jasmin-dev/lib/jasminclasses-trunk.jar
  50. cat soot-dev/ant.settings.template | sed \
  51. -e "s/.*\(jastaddfrontend.loc=\).*/3..\/JastAddExtensions\/SootJastAddJ/" \
  52. -e "s/.*\(polyglot.jar=\).*/3..\/polyglotclasses-1.3.5.jar/" \
  53. -e "s/.*\(jasmin.jar=\).*/3..\/jasmin-dev\/lib\/jasminclasses-trunk.jar/" \
  54. > soot-dev/ant.settings
  55.  
  56. # Change into the soot-dev directory and build the
  57. # sootclasses-trunk.jar file, and change back out of the directory:
  58. cd soot-dev
  59. ant classesjar
  60. cd ..
  61.  
  62. cp soot-dev/lib/sootclasses-trunk.jar .

Print This Print This   Email This Email This

A HotSpot Java Error, a Bus Error and a Segmentation Fault

January 30th, 2010, 3:10 pm by Mathias

When I run Soot to create a call graph of DrJava, I get the aforementioned HotSpot Java error on Windows with Java 1.6.0_18.

On Mac OS X 10.4 with Java 1.5.0_19, I get a “Bus error” (Java exit status 138).
On Red Hat Enterprise Linux 5 with Java 1.6.0_18, I get a “Segmentation fault” (Java exit status 139).

Fun, fun! At least it’s consistently not working. They probably all have the same cause.

Print This Print This   Email This Email This

Mint Paper Accepted to PLDI 2010

January 30th, 2010, 10:11 am by Mathias

I’m happy to report that our Mint paper “Mint: Java Multi-stage Programming Using Weak Separability” has been accepted to PLDI 2010 in Toronto!

I couldn’t find the deadline for submitting the camera-ready version yet, and the reviewer and referee comments aren’t final yet, but I’ll let you know once I know more.

The only disappointing issue is that I might not be able to go to Toronto. My US student visa expires in May, which isn’t a problem as long as I don’t leave the country ;)

Print This Print This   Email This Email This

Subversion “obliterate”

January 29th, 2010, 2:28 pm by Mathias

Apparently, Subversion is adding support for an “obliterate” command that can delete a file completely, including from the revision history.

I once had to do this because I accidentally added a license file that needed to be kept private into the repository. I had quickly deleted the license file, but it was still available in the revision history.

Since Subversion does not provide a command to completely remove a file from the repository (such as Perforce with “p4 obliterate”), I had to do a dump of the Subversion repository (using rsync and svnadmin dump), then filter out the file (svndumpfilter), and then import the repository into SourceForge again using the migration function (I don’t know how this works on other repositories outside of SourceForge, and SourceForge has changed a lot too during the last two years).

I just wanted to give people some starting points by mentioning svnadmin dump and svndumpfilter.

Print This Print This   Email This Email This

More Details on Soot and -allow-phantom-refs

January 29th, 2010, 11:24 am by Mathias

In the previous post I mentioned that I’m trying to create a call graph of all of DrJava using Soot. Since DrJava is a cross-platform application, there are classes that get compiled and used only on certain operating systems. The classes in the com.apple.eawt package, for instance, are only used on the Mac.

That means that Soot doesn’t normally find these classes when generating the call graph with Sun JDKs:

resolving [from .class]: edu.rice.cs.drjava.platform.MacPlatform$1
Exception in thread "main" java.lang.RuntimeException:
couldn't find class: com.apple.eawt.ApplicationListener
(is your soot-class-path set properly?)
    at soot.SootResolver.bringToHierarchy(SootResolver.java:184)
    at soot.SootResolver.bringToSignatures(SootResolver.java:219)
    at soot.SootResolver.bringToBodies(SootResolver.java:260)
    at soot.SootResolver.processResolveWorklist(SootResolver.java:135)
    at soot.SootResolver.resolveClass(SootResolver.java:124)
    at soot.Scene.loadClass(Scene.java:390)
    at soot.Scene.loadClassAndSupport(Scene.java:375)
    at soot.Scene.loadNecessaryClasses(Scene.java:963)
    at soot.Main.run(Main.java:169)
    at soot.Main.main(Main.java:145)

Setting the Soot -allow-phantom-refs option doesn’t really help; it gets past the initial stages, but later still has errors:

Exception in thread "main" soot.AbstractSootMethodRef$ClassResolutionFailedException:
Class com.apple.eawt.ApplicationEvent doesn't have method setHandled([boolean]) : void;
failed to resolve in superclasses and interfacesLooking in com.apple.eawt.ApplicationEvent
which has methods []
    at soot.AbstractSootMethodRef.resolve(AbstractSootMethodRef.java:135)
    at soot.AbstractSootMethodRef.resolve(AbstractSootMethodRef.java:95)
    at soot.jimple.internal.AbstractInvokeExpr.getMethod(AbstractInvokeExpr.java:54)
    at soot.jimple.toolkits.callgraph.OnFlyCallGraphBuilder.getImplicitTargets
        (OnFlyCallGraphBuilder.java:234)
    at soot.jimple.toolkits.callgraph.OnFlyCallGraphBuilder.processNewMethod
        (OnFlyCallGraphBuilder.java:182)
    at soot.jimple.toolkits.callgraph.OnFlyCallGraphBuilder.processReachables
        (OnFlyCallGraphBuilder.java:81)
    at soot.jimple.toolkits.callgraph.CallGraphBuilder.build(CallGraphBuilder.java:84)
    at soot.jimple.toolkits.callgraph.CHATransformer.internalTransform(CHATransformer.java:43)
    at soot.SceneTransformer.transform(SceneTransformer.java:39)
    at soot.SceneTransformer.transform(SceneTransformer.java:45)
    at soot.SceneTransformer.transform(SceneTransformer.java:50)
    at dk.brics.soot.callgraphs.CallGraphExample$2.internalTransform(CallGraphExample.java:88)
    at soot.SceneTransformer.transform(SceneTransformer.java:39)
    at soot.Transform.apply(Transform.java:89)
    at soot.ScenePack.internalApply(ScenePack.java:43)
    at soot.Pack.apply(Pack.java:114)
    at soot.PackManager.runWholeProgramPacks(PackManager.java:409)
    at soot.PackManager.runPacks(PackManager.java:329)
    at soot.Main.run(Main.java:202)
    at soot.Main.main(Main.java:145)

What I did instead was make the Apple classes available on Windows and Linux as well, just on the Soot classpath (they aren’t actually loaded by the JVM), but then I run into an 8-year-old Java bug in the garbage collector. Fixing Soot is more likely than fixing the JVM.

Update

After checking out Soot from the svn repository and building it from scratch, the Soot problem has gone away, but now I still run into the 8-year-old Java bug in the garbage collector.

Print This Print This   Email This Email This

Java Bug 4396719 – Mark Sweep stack overflow on deeply nested Object arrays

January 29th, 2010, 6:39 am by Mathias

I’m trying to create a call graph of all of DrJava using Soot. DrJava is a cross-platform application that has some classes that get compiled and used only on certain operating systems; for example, the com.apple.eawt package is only used on the Mac. That means that Soot doesn’t normally find these classes when generating the call graph with Sun JDKs. Setting the Soot -allow-phantom-refs option doesn’t really help; it gets past the initial stages, but later still has errors. What I did instead was make the Apple classes available on Windows and Linux as well, just on the Soot classpath (they aren’t actually loaded by the JVM).

Now I’m getting a HotSpot Java error. Except for memory addresses, it is identical to this bug 6849033, filed in June 2009. The bug report, however, is closed because it is a duplicate of bug 4396719 – Mark Sweep stack overflow on deeply nested Object arrays… which isn’t in the database.

Why is that bug not in the database? Probably for security reasons, which isn’t immediately obvious. The fact that the original bug report to which all other bugs are referring isn’t available makes it hard to figure out what’s going on. What I find really shocking, though, is that the first bug I can find that lists the ominous bug 4396719 as original bug report is from February 2002: bug 4641910. That means this bug has been known and not fixed for eight years!

Some other duplicate bug reports provide a description of the problem:

The problem is in the Garbage collection subsystem, dealing with the very deeply nested arrays (an array who’s element is an array who’s element is an array…)

This also makes it clear why there are security concerns that lead to the removal of the bug report: It is fairly simple to write Java code that is perfectly legal and that passes the Java verifier, but that will cause the JVM to crash. This can be used for a denial-of-service attack in Java plugins.

The source for exploits is out there, this bug has been known for over eight years, some duplicate bug reports still describe the problem. Security through obscurity won’t work, especially not if you are this sloppy. I’m disappointed, Sun!

Print This Print This   Email This Email This

Sometimes I Love Myself

January 25th, 2010, 2:46 pm by Mathias

Sometimes I have those moments when something small that I did brings me tremendous joy.

This just happened when I was using DrJava with Soot. I don’t know the Soot framework, so the “Additional Javadoc URLs” feature that I introduced some time in 2009 comes in really handy.

I just entered “http://www.sable.mcgill.ca/soot/doc” as URL, and now I have auto-completion for class names and the Javadocs available at the touch of a button! Nothing too fantastic, but remarkable for DrJava nonetheless.

PS: Hopefully my IT hell will get a little less hellish tomorrow. We’ve been thinking about adding a PCI card to my desktop (finland.cs) at work, only to discover that this Dell i7 computer doesn’t have PCI, only PCI Express. But there is a solution: The old finland.cs, now our Hudson server called denmark.cs, has a PCI Express x16 card that we had running with dual heads. denmark.cs doesn’t need dual head capability now; in fact, it mostly runs headless anyway. So we’ll swap the graphics cards in denmark.cs and finland.cs and hope I’ll have two working monitors again.

Print This Print This   Email This Email This

IT Hell

January 22nd, 2010, 4:40 pm by Mathias

Building emacs22 to replace emacs21, so I can install yasnippet, so I can install scala-tool-support, because I can’t install Eclipse since it requires Mac OS 10.5 and I only have 10.4 because Apple doesn’t support Java 6 on 32-bit Macs…

Sitting on a couch in the lobby at work, because my spiffy i7 Dell desktop runs the dual head configuration with graphics speed reminiscent of the 1980s. RHEL5 seems to have problems with the ATI PCI-Express card, and even our otherwise very knowledgeable Linux IT system administrator is having problems…

Reading some papers that took forever to print because one of the two huge LaserJets is getting a paper jam with every page, and it seems to be impossible to just print to the one that works…

Print This Print This   Email This Email This

Broken Things 2010

January 17th, 2010, 12:18 pm by Mathias

So far, it seems like 2010 is a year of broken things.

Mr. Coffee, my coffee maker, broke. I loved the guy, so I immediately replaced him with his younger brother.

The power supply fan in my Dell at home is close to dying. It makes a terrible, agonizing rattling sound. I bought a replacement power supply, but haven’t installed it yet. The only reason why it’s been bearable so far is that it has been rather cold on most days, so the fan isn’t running very much.

My Microsoft Natural Keyboard Pro at home broke in an interesting way. Some key combinations don’t work anymore, for example Left Ctrl-F. Right Ctrl-F works. I know the Natural Keyboard Pro isn’t the most ergonomic keyboard out there, but I’ve gotten used to it. What do I replace it with? I’m thinking the Microsoft Natural Ergonomic Keyboard 4000, which one of my office mates uses, but I’m not sure I’ll immediately like it.

Oh, and yesterday GMail ate my draft.

At least no broken bones so far. Maybe I shouldn’t complain.

Print This Print This   Email This Email This

Another Possible Improvement

January 12th, 2010, 5:04 pm by Mathias

On the other hand, I think I can re-enable checking if the event thread has finished and generating EventThreadStillProcessingErrors in the “update” Runnable that sets the test thread group the event thread uses, at least in certain cases.

It is possible that test A has generated the EventThreadStillProcessingError by putting a long Runnable aRunnable on the event queue. When test B starts executing, it puts an update Runnable updateB on the event queue, but it doesn’t execute yet.

If aRunnable finishes now and updateB executes while test B is still running, we can enable checking the event thread again. The event thread has “caught up” with the tests, so to speak.

If, on the other hand, test B finishes before aRunnable finishes, then test C will begin and enqueue an update Runnable updateC. Now aRunnable finishes and updateB executes. Here we clearly don’t want to enable checking, because test C is already executing.

So, if the test’s thread group and the new thread group for the event thread are identical, we can re-enable checking the event thread, because that means the event thread has caught up sufficiently.

Print This Print This   Email This Email This

Another Possible Problem

January 12th, 2010, 4:29 pm by Mathias

I think I have just realized that this still isn’t good enough. Now we know that there aren’t any more events, but it is conceivable that a Runnable executing just before the token Runnable has started new threads. Those threads could fail, or add new “token” Runnables. It seems like the whole thing needs to be put in a loop.

Print This Print This   Email This Email This

New Release of ConcJUnit: 20100112

January 12th, 2010, 4:28 pm by Mathias

I’ve just made a new release of ConcJUnit: 20100112. This release contains an important addition that I had been thinking about for a while.

ConcJUnit already detected failures and uncaught exceptions in the event thread, but since the event thread is a daemon thread started by the system, it is not part of the “join” and “lucky” checks. It is not required to join the event thread with the test’s main thread (in fact, it’s not really possible, since there is no way to terminate the event thread), and that also means that I do not check if the event thread finished processing.

That was a problem, of course. It was possible to put a Runnable on the event queue and then end the test, resulting in a success, even though the code in the Runnable may still fail.

I have now added code that checks if the event thread is running, and if that is the case, we check if the event queue is empty, as it should be. If it isn’t, then we issue an EventThreadStillProcessingError, which is a subclass of a NoJoinError.

However, an empty event queue does not guarantee that the event thread has finished processing. There way still be a Runnable executing in the event thread; there just aren’t any more events queued up after it. So we need to make sure that there isn’t an event being processed right now; I currently do that by adding a “token” Runnable to the event queue and requiring that it executes immediately1.

But even if the token Runnable gets to execute right away, it isn’t guaranteed that the test’s events have all been processed. We also have to ensure that after we checked that the event queue was empty and before the token Runnable began executing, no additional Runnable objects were added to the event queue. Those additional events would have been added after the token Runnable, so inside the token Runnable we check again if the event queue is empty.

If the token Runnable executed immediately and the event queue is still empty when it executes, then we know that there aren’t anymore events that need to be processed and that could fail, and the test has completed in its entirety. We already checked that there aren’t any more regular threads around that could add new events, and the event thread has finished processing all Runnables.

When a EventThreadStillProcessingError is generated, then the event thread is still executing code belonging to a test that has just ended. I didn’t want to let the test wait for the event thread to finish, I want to allow it to move on. This is sort of a greedy process: Let’s run as many tests as we can. Waiting for the event thread, if not specified by the test code, could mean waiting forever if the event thread is deadlocked. However, if it isn’t deadlocked, and code there is still making progress, then it may also still fail after a new test has already started to execute. The event thread is shared among all tests, so I had to make sure that a failure in the event thread caused by a Runnable belonging to the previous test doesn’t fail the test currently executing.

I do this by maintaining a field containing the test thread group belonging to the current Runnable in the event thread. If the event thread is not running yet, then that field is updated directly at the beginning of each test. If the event thread is running, then we want all Runnables already in the event queue to still notify the test group of the previous test. All future Runnables, however, should use the current test’s thread group, so we update the field in an “update” Runnable which will execute when all Runnables belonging to the previous test have been processed.

Of course, if the event thread is deadlocked, then the update Runnable will never execute. This isn’t any worse, though, than JUnit already behaves. ConcJUnit will still allow tests that do not need the event thread to execute. When a test is executed that requires the event thread, for example by executing a invokeAndWait, then that test will hang. But at least there will have been a EventThreadStillProcessingError pointing out which test is responsible for it.

Another small problem is that once an EventThreadStillProcessingError has been generated, I do not want all following tests to also fail with that error. The event thread may still contain Runnables from the first test that was flawed that way, for example if the event thread is deadlocked. Therefore, once an EventThreadStillProcessingError has occurred, checking whether the event thread has finished is disabled. That means that only one EventThreadStillProcessingError will ever be generated. Later tests that also have this problem may go undetected until the first test has been fixed.


Footnotes:
  1. Immediately practically means “very quickly”; currently within 100 ms. That’s not exactly the same, but hopefully close enough. [back]

Print This Print This   Email This Email This

Auto-Upgrade to WordPress 2.9

January 3rd, 2010, 1:50 am by Mathias

I just performed an WordPress auto-upgrade to version 2.9.

Version 2.9 requires MySQL version 4.1.2, and 1&1 was only running version 4.0.27. However, I found out that MySQL 5.0 is also running, so I needed to export the MySQL 4.0 database, create a new MySQL 5.0 database, and import the old data. The details of this, including some editing of the exported SQL commands, can be found on Don Campbell’s blog.

If you notice any errors on this blog, please let me know.

PS: Happy new year.

Print This Print This   Email This Email This

Out-of-Office Auto-Replies

December 21st, 2009, 9:14 am by Mathias

Great. I’m starting to get flooded by out-of-office auto-replies from the AP CS mailing list again.

I keep monitoring that mailing list for mentionings of DrJava, so I can make sure we help high school teachers with potential problems. I just posted a reply, reminding a user to also install the JDK when installing DrJava. Unfortunately, it’s past the end of the semester at most institutions now, and that means that a bunch of people won’t be reading their email now.

And they think they need to tell people that they won’t be reading their email. So they set up out-of-office auto-replies that reply to every message they receive. Including posts from the mailing list they chose to subscribe to. At least the AP CS mailing list is set up to list the individual post writer as sender, and not the entire mailing list, so the auto-replies just go to me and don’t cause a vicious cycle of auto-replies to auto-replies, and so on.

Still: These people chose to subscribe to the mailing list. I’m not writing to them personally. Can’t they have the decency and foresight to unsubscribe or except the mailing list from the auto-replies? Are out-of-office auto-replies really necessary?

Print This Print This   Email This Email This

Cygwin, Subversion and End of Lines

December 14th, 2009, 2:35 am by Mathias

I got myself into a bit of a problem when I tried to set the automatic end-of-line style property for our text files in Subversion. I wanted to use “native”, because that should automatically convert all line endings to LF (“\n”) on Unix and Mac, and to CR LF (“\r\n”) on Windows.

This seemed to work, but unfortunately the language level tests started breaking. It was pretty clear that this had to be a line ending issue. I couldn’t figure out why, though, and I went back and forth and changed the eol-style, ran dos2unix or unix2dos, and because the failures were only appearing after an update or checkout on another system, all of this went into the repository. All in all, it took me from revision 5144 to revision 5163 to get this right. This is shameful.

In retrospect, I should have done this in a branch, but svn was behaving very strangely, and I was worried that I might get it to work in the branch, but then something would go wrong when copying the files back into the trunk. I think there were two things that confused me:

  1. On Windows (or perhaps on Cygwin), Subversion seems to be line-ending insensitive. I can take a file that had Unix line endings, run unix2dos on it, the file had changed, but Subversion would not list it as modified.
  2. On Cygwin, Subversion’s “native” line ending is not the Windows default of CR LF, but LF, just like on Unix systems. That meant that the files with the “expected” outcome still contained LF line endings, but the files we were generating contained CR LF line endings. This is not well documented.

I was close to forcing LF line endings everywhere, but then decided to stick with “native”. If someone actually has a non-Cygwin Windows Subversion client, this may work, and I had to make the unit tests line ending-insensitive anyway.

There was another issue that gave me a hard time for an hour or so: The unit tests use some class files and make sure that they are newer than the source files. I had touched the source files when I changed the line endings, but the class files had not been recompiled. This caused the a couple of unit tests to fail with a nondescript error message. I had to trace the execution of the test to get to the following line to understand the problem:

if (sourceFile.lastModified() > classModTime) {

As a hack, I just Unix-touch the class files to give them a more recent time stamp. I tried to recompile the class files, but that wasn’t possible:

  1. Some of the class files (B.class, Doh.class, TestWeirdStuff.class) don’t have any associated source (it’s missing).
  2. Wow.dj0 contains the public keyword, which is not permitted in the elementary level.
  3. The classes Tom.dj1 and Jerry.dj1 contain a cyclic inheritance graph, so they cannot be compiled, yet their class files exist.

I kept the class files. I didn’t want to re-engineer or understand the unit tests more than I had to. Considering that I had another sudden failure with the unit tests a few weeks ago, I don’t think they are well engineered.

As a side note: I love bash. I don’t know if it’s actually helping or hurting me (kind of like LaTeX), but writing something like this is cool every time:

find . -type f -not -path "*.svn*"|xargs -n 1 -I {} -i bash -c 'if [ "svn propget svn:eol-style {}" == "LF" ]; then echo {}; fi'| xargs -n 1 dos2unix

Or perhaps a Unix guru out there has a better way to run dos2unix on all files that have been marked with the “LF” end-of-line style property in Subversion?

Print This Print This   Email This Email This

Submitted Publication Version of SIGCSE 2010 Paper

December 4th, 2009, 5:10 pm by Mathias

I just submitted the publication version of our SIGCSE 2010 paper, Test-First Java Concurrency for the Classroom.

Now I’m waiting for the copyright form to be sent, and I’m wondering why that’s not done automatically…

Print This Print This   Email This Email This