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  

Out-of-Office Auto-Replies

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?

Share
Posted in Ramblings | Leave a comment

Print This Post Print This Post  

Cygwin, Subversion and End of Lines

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?

Share
Posted in DrJava | Leave a comment

Print This Post Print This Post  

Submitted Publication Version of SIGCSE 2010 Paper

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…

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Snow

As someone who knows what snow actually is, I’m picky about what I call snow. When my fellow Houstonians say “it’s snowing”, I tend to say “no, this is sleet (@Apparently sleet is known as partially melted snow in the US.@).” But I have to agree with them now: It is definitely snowing in Houston right now. It is also colder in Houston than in Bremen.

Houston Doppler Radar

Houston Doppler Radar

Update

Now it is colder in Houston during the day than it is in Helsinki, Finland, at night.

Houston Doppler with Lots of Snow

Houston Doppler with Lots of Snow

Update

Snow Day at Rice University, click for Flickr ste

Snow Day at Rice University, click for Flickr site

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

Another Sample Bug for Yield

I coded up two more examples to test the yield strategy. The “split synchronized” example doesn’t work that well (yet), because it fails even without the added yields. I’m looking for common bugs that aren’t obvious.

Thread remover = new Thread() {
public void run() {
while(l.size()>0) {
l.remove(0);
}
}
};
Thread reader = new Thread() {
public void run() {
for(int i=0; i<10; ++i) { if (l.size()==0) { break; } int e = l.get(l.size()-1); // l.size and l.get not atomic } } };

The important thing here is that the calls to l.size() and l.get may get interrupted by the other thread performing an l.remove(0). I know that this happens quite frequently and is not always as obvious as here (in DrJava, this happened when we tried to append text to a document; append was implemented "insert text at index", and the length was used as index), but right now I'm unable to reproduce that in a short example.

However, I have another example from my COMP 402 course last semester that benefits from the inserted yields:

class WaitRunnable implements Runnable {
public void run() {
sleep(1000);
while(true) {
synchronized(_lock) {
if (_flag) break;
}
// lock dropped here!
synchronized(_lock) {
try { _lock.wait(); }
catch(InterruptedException ie) { /* ignore */ }
}
}
}
}

The problem here is that the condition _flag is checked, but before wait() is called, the lock is dropped. Therefore, another thread may call notify() and change _flag and allow the first thread to enter a wait() from which it will not be woken up.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Getting Back on That Concurrency Horse

After a lot of work on Mint, I’m now focusing on the concurrent unit testing project again. I had to fight some apparent code rot, which was probably caused by changes from Java 5 to Java 6, but now everything is working again.

I have a nice example that shows that double-checked locking is broken. With a yield probability of 0.5 and yields in all places (thread start, thread run, thread exit, thread join, before notifies, after notifies, before waits, after waits, before synchronized and after synchronized), it usually shows up in under 10 iterations.

It would be nice to have a simpler way of setting these parameters, e.g. by using an annotation on the test:

@Test(yieldProb=0.5, beforeSynchronized=false)
public void testFoo() { ... }

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Double.equals for NaN and -0.0

I just fixed two bugs in DrJava that had to do with boxed floating-point comparisons of NaN and -0.0.

Both bugs had the same cause, a difference between the behavior of primitive == and the equals method in Double and Float.

According to IEEE 754, any NaN isn’t equal to anything, not even itself. Therefore, Double.NaN==Double.NaN should evaluate to false. On the other hand, positive and negative zero are the same (even though they have different encodings), so 0.0==-0.0 should evaluate to true. This is the case for the primitive types double and float, but not for the boxed types Double and Float.

This may be surprising, but the boxed types had additional contracts to fulfill regarding the behavior of equals and hashCode in hash tables. It was decided that it was more important to successfully look up floating-point values in hash tables, so new Double(Double.NaN).equals(new Double(Double.NaN)) returns true, and new Double(0.0).equals(new Double(-0.0)) returns false. Try it.

In Dynamic Java, the interpreter in DrJava, we internally used boxed types when comparing primitives, just because that way, we could write the equals method more easily. Now I created special cases for floating-point numbers that unboxes the values and eschews the equals method.

Share
Posted in DrJava | Leave a comment

Print This Post Print This Post  

CSEE&T Paper Not Accepted

As expected, the paper I submitted for CSEE&T back in October did not get accepted. But that was a long shot anyway, and I already have something else for it in mind.

Share
Posted in Research | Leave a comment

Print This Post Print This Post  

Happy Thanksgiving

Happy Thanksgiving, everyone! I was fortunate to spend a wonderful day with Walid, Corky and Corky’s family. Thank you.

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

Remembered Number Significance

Memories can be strange. A lot of people around me are probably now having memories triggered by (turkey) smells. I have memories triggered by numbers.

Our Hudson build server just notified us of a unit test failure after a recent commit. It was a:

java.lang.NullPointerException
      at edu.rice.cs.drjava.model.definitions.CompoundUndoManager$1.run(CompoundUndoManager.java:216)

The line number, 216 immediately hat a strong meaning for me: general protection fault, some kind of protected mode error (to plug my first programming website)!

Of course, that was ages ago, when I worked with Borland Pascal 7, but somehow the number 216 has retained its significance to me.

Share
Posted in DrJava, Ramblings | Leave a comment

Print This Post Print This Post