Problems

Lately 1&1, the hosting service that my blog runs. on has had a few problems. I got the funniest/strangest/most annoying mixture of error messages (“500”, “too many files open”, “CGI error -1”, …), so I couldn’t post exactly when I wanted to post.

I’ve had other problems too, though. For DrJava, I’ve tried to detect if it is running on a tablet PC OS to present the “Enable ‘Forcefully Quit DrJava’?” dialog just before quitting, but only on tablet PCs. I couldn’t do it; not from within Java. Of the ways presented by Microsoft, the only option available to Java was checking for the existence of inkobj.dll, and that file turned out to exist on Windows 2003 Server as well, and this method wouldn’t be Vista-proof anyway. So I’ve just given up on this issue. Now I’ve definitely put way over one man-week into the tablet PC problem *sigh*

On the thread checker front, I noticed last Monday morning — a week ago — that some methods would crash, often with a VerifyError that complained about incorrect PC values. I couldn’t explain it… That’s serious business; it’s basically one form of malformed class file. On Saturday morning, I finally figured out. It was a slow progress, though, because there was so much to do this week and I was sick from Tuesday to Thursday. My first step was to extend ClassDumper, my custom version of javap to perform a check for every method whether the PC values actually fall on instruction boundaries. In some cases, all static methods, they didn’t. That was clue number 1. When tracing through my program, I noticed that some bytecode might be inserted, assuming that further bytecode would get inserted too, but that wasn’t the case because I excluded static methods from ONLY\_AFTER\_REALIZE.

There was a second problem, though, and this was what made the diagnosis so complex. In some cases, Java complained that it expected an array or object instance on the stack. Why was it giving me that error in a few cases, but generally it was working? Well, I inserted these checks always at the very beginning of the method. In case of constructors, though, that would be before the this() or super() call, so aload_0 or this wasn’t properly initialized yet and was probably still null. Now I’m treating constructors differently and insert the this() or super() call.

On Friday, I just had to overcome my sickness to deal with an abstract submission for my upcoming poster. I wanted to make sure Corky got a chance to read my suggested abstract. Here is the submitted version:

Title: Practical Tools for Testing for Large Concurrent Programs

Authors: Professor Robert “Corky” Cartwright and Mathias Ricken

Abstract:

In our experience with developing production programs in Java, unit testing has proven effective in assuring the reliability of code with a single thread of control. Unfortunately, unit testing has proved much less effective in assuring the reliability of code with multiple threads of control, often simply because the JUnit testing framework silently ignores failures in auxiliary threads. Java libraries and user programs frequently make assumptions about the threading context in which they execute, but these assumptions are rarely enforced by the actual code and typically only appear in program documentation. Since thread scheduling is non-deterministic, a unit
test can succeed on one run and fail on the next, or repeatedly succeed on one platform and occasionally fail on another.

To improve test-driven development for concurrent programs, we are developing

  1. an extension of the JUnit framework, actively supporting the developer by treating tests that could silently ignore failures in auxiliary threads as test errors;
  2. a lightweight annotation language, which can be used to specify and check the threading properties of both existing and new code; and
  3. a testing framework that can execute unit tests according to a specified set of recorded or generated schedules, elevating the unit testing of concurrent programs to a rigorous, deterministic process.

As you can see, it puts a lot more weight on practical tools that are within my reach, like an extension of JUnit that helps the developer create multithreaded tests that don’t vacuously succeed, e.g. when no default exception handler is installed to catch exceptions (unit test failures are exceptions) in auxiliary threads. My proposal goes further than that, though; I want to force the user to join with all threads that have been created, thereby guaranteeing that failures in other threads cannot be missed. In the example below, the test would likely succeed even with an exception handler installed:

1
2
3
4
5
6
7
8
public void testNoJoin() {
    (new Thread(new Runnable() {
        public void run() {
            /* some lengthy computation */
            fail("unconditionally");
        }
    })).start();
}

I also changed the error window in DrJava to also contain the configuration file information (basically the preference settings) in addition to the stack trace and Java properties. I’ve been happy to see that many users actually include this data, so more data can only help us. If users actually paste that information, too, now we don’t have to ask anymore “Do you have ‘automatically close comments’ enabled?”.

And finally I also had to rewrite the submission script for COMP 311, the class I TA this semester, as students were running into problems with submitting a larger (relatively small; about 50 were enough) number of files. The scripts were written in Python by James Sasitorn. I think he’s done a great job; there are some rough edges, but hey, the grading scripts do work! Where else do you see that? There were some changes to the Owlnet environment this semester that have tripped us up a few times, so I did the first round of grading myself this weekend, and the next time around I’ll show the other TAs how to do it, and then we’ll start rotating. The autograding is a great simplifier, but it’s not trivial and still took me about 5 hours to do Saturday morning.

Anyway, my TA work for COMP 311 really amuses me because it really emphasizes one mantra that I’ve had for a long time: Language doesn’t matter. Students can submit their assignments in Java, OCaml and Scheme, so I have to be relatively fluent in all of them, and the scripts were written in Python. I’ve been using and maintaining the scripts for two years now, and I never formally learned it. Does that matter? No. I see many “newbies” to computer science/software engineering ask questions like “Should I still learn Visual C++ 7 when VC++ 8 is almost out the door?” and freak out because there are so many programs they should be familiar with, and so many certification courses they could take. It doesn’t matter if you truly understand what you’re doing. </rant>

Share

About Mathias

Software development engineer. Principal developer of DrJava. Recent Ph.D. graduate from the Department of Computer Science at Rice University.
This entry was posted in Concurrent Unit Testing, DrJava, Uncategorized. Bookmark the permalink.

Leave a Reply