New Mint Release: r15085

I just created a new release of Mint and DrJava with Mint: February 12, 2010 (r15085). The release is available from the Mint implementation page:

The two changes since the last release involve CSP values and escapes in bracket statements. Instead of storing CSP values in a CSP table, we now store CSP values in individual fields. This reduces the overhead by eliminating an array lookup. The serializer benchmark benefited from this, for example.

We now also allow non-void escapes in bracket statements. For example, the following code is now allowed:

Code x = <| 1 |>;
Code c = <| { `x } |>;

In the past, this caused an error because 1 was not a statement. The Mint compiler now accepts this and discards the result of the escape if it is used in statement form, but it does emit a warning.

(Re-posted from The Java Mint Blog.)

Share
Posted in Mint | 1 Comment

Print This Post Print This Post  

Mint Talk Video

The video recording of the Mint talk I gave on Monday is now available on vimeo:

Mint: A Multi-stage Extension of Java (Mathias Ricken) from Mathias Ricken on Vimeo.

Share
Posted in Mint, Pictures | Leave a comment

Print This Post Print This Post  

Pictures from Yesterday’s Talk

Here are a few pictures from yesterday’s talk about Mint.

Multi-stage Programming MSP in Java

MSP in Java 2 Staged power Function

Weak Separability Thank You

Share
Posted in Graduate School, Mint, Pictures | Leave a comment

Print This Post Print This Post  

Mint Talk in COMP 600

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.

Share
Posted in Graduate School, Mint | 1 Comment

Print This Post Print This Post  

Presentation: Mint: A Multi-stage Extension of Java

Mint: A Multi-stage Extension of Java
(PowerPoint, PDF, view embedded)
Video recording available on vimeo.

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
).

Share
Posted in Mint, Publications | 2 Comments

Print This Post Print This Post  

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

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 type system and the effect of staging on the performance of Java programs.

Share
Posted in Mint, Publications | 2 Comments

Print This Post Print This Post  

Java Bug 4396719 Work-Around?

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.

Share
Posted in Concurrent Unit Testing, DrJava | 1 Comment

Print This Post Print This Post  

Soot Build Instructions

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
    Unit jump = (Unit) units.getSuccOf(next.get(next.size() - 1));

  17. read
    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

#!/bin/bash

# Make sure you have Ant ant the JDK (5 or newer) installed.
# Check out and download all of these code bases in the same directory.
# Download Polyglot from http://www.sable.mcgill.ca/soot/soot_download.html:
wget http://www.sable.mcgill.ca/software/polyglotclasses-1.3.5.jar

# Check out Soot from https://svn.sable.mcgill.ca/soot/soot/trunk:
svn checkout https://svn.sable.mcgill.ca/soot/soot/trunk soot-dev

# Check out Jasmin from https://svn.sable.mcgill.ca/soot/jasmin/trunk:
svn checkout https://svn.sable.mcgill.ca/soot/jasmin/trunk jasmin-dev

# Check out JastAddJ from http://svn.jastadd.org/projects/trunk/JastAddJ:
svn co http://svn.jastadd.org/projects/trunk/JastAddJ

# Check out JastAddExtensions from
# http://svn.jastadd.org/projects/trunk/JastAddExtensions:
svn co http://svn.jastadd.org/projects/trunk/JastAddExtensions

# Copy jasmin-dev/ant.settings.template to jasmin-dev/ant.settings:
# Edit jasmin-dev/ant.settings so it contains the following lines:
# java_cup.jar=../polyglotclasses-1.3.5.jar
# jasmin.version=trunk
cat jasmin-dev/ant.settings.template | sed \
-e "s/.*\(java_cup.jar=\).*/\1..\/polyglotclasses-1.3.5.jar/" \
-e "s/.*\(jasmin.version=\).*/\1trunk/" \
> jasmin-dev/ant.settings

# 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 ..

# The freshly built Jasmin jar file is
# jasmin-dev/lib/jasminclasses-trunk.jar. 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 ../..

# Copy soot-dev/ant.settings.template to soot-dev/ant.settings:
# 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
cat soot-dev/ant.settings.template | sed \
-e "s/.*\(jastaddfrontend.loc=\).*/\1..\/JastAddExtensions\/SootJastAddJ/" \
-e "s/.*\(polyglot.jar=\).*/\1..\/polyglotclasses-1.3.5.jar/" \
-e "s/.*\(jasmin.jar=\).*/\1..\/jasmin-dev\/lib\/jasminclasses-trunk.jar/" \
> soot-dev/ant.settings

# 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 ..

cp soot-dev/lib/sootclasses-trunk.jar .

Share
Posted in Concurrent Unit Testing | 1 Comment

Print This Post Print This Post  

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

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.

Share
Posted in Concurrent Unit Testing, Ramblings | Leave a comment

Print This Post Print This Post  

Mint Paper Accepted to PLDI 2010

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 ;)

Share
Posted in Mint | Leave a comment

Print This Post Print This Post  

Subversion “obliterate”

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.

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

More Details on Soot and -allow-phantom-refs

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.

Share
Posted in Concurrent Unit Testing, DrJava | 1 Comment

Print This Post Print This Post  

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

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!

Share
Posted in Concurrent Unit Testing, DrJava, Ramblings | 4 Comments

Print This Post Print This Post  

Sometimes I Love Myself

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.

Share
Posted in DrJava, Ramblings | Leave a comment

Print This Post Print This Post  

IT Hell

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…

Share
Posted in Ramblings | 2 Comments

Print This Post Print This Post  

Broken Things 2010

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.

Share
Posted in Ramblings | 1 Comment

Print This Post Print This Post  

Another Possible Improvement

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.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Another Possible Problem

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.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

New Release of ConcJUnit: 20100112

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 immediately (@ Immediately practically means “very quickly”; currently within 100 ms. That’s not exactly the same, but hopefully close enough. @).

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.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Auto-Upgrade to WordPress 2.9

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.

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post