Tuesday, March 22, 2016

Why Does Canceling Operations in Eclipse Never Work?

Well... saying "never works" is too extreme, so let's say "does not work often enough". Often enough, so the majority of users do not trust the red square button for canceling background operations.

Let's have a look at some quotes from a famous web site for collecting (mostly negative) feedback about Eclipse.
When I cancel a task, it hangs and ends up taking longer than it would have taken to let it finish.
Cancelling never works. Trying to build a project. It get's stuck. I cancel it. It cancels for 10 minutes. I have to force quit it again.
Why in gods name do you have a cancel task option if it's never going to cancel the @#$% task?? Is this some kind of sick joke?
There is also a blog post written back in 2006, which gives a more detailed picture of a user experience with the cancel button.

Why does Eclipse provide a cancel button that does not work?


Let's have a look how the Cancel Operation button is implemented. When you click on the red square button, the Eclipse Platform raises a "cancellation" flag for the running background operation. Then it is up to the latter to check if that flag is raised and terminate itself.

In other words, the Eclipse Platform has no power to terminate background operations, but only to send them a request for cancellation. If the operation is implemented in a proper way, i.e. frequently checks for the cancellation flag, it will promptly terminate itself. Alternatively, a poor implementation may totally miss checking the cancellation flag and finish as if the user has not pushed the cancel button.

In an even worse scenario, the background operation may check for the cancellation flag, but instead of terminating itself immediately, it may try reverting everything it has done so far. While this may be a valid approach for some use cases where keeping data consistency is critical, most of the time it is just an over-engineering. This way an operation that was canceled in the middle of the execution, may take longer than if it has not been canceled at all. This leads to even more frustrating user experience.

What is the solution?


Unfortunately, there is no direct solution for you as a user to apply to your IDE. The issue is caused by a weak code implementation in the plugins providing the background operations and it must be fixed there. There is no magic fix that can be implemented in the Eclipse Platform alone.

However, there is still something you can do:
  1. Report the issue - yes, please open a bug if you stumble upon an operation that does not terminate promptly when you hit the cancel button. This is a good small step to make a difference.
  2. Keep your Eclipse up-to-date with the latest version of all plugins with the hope that this kind of issues will be resolved over time.
If you are an Eclipse plugin developer then you should design carefully your background operation, so users are able to cancel them. It is natural to focus on the happy path when implementing a new operation. But it won't be always the case where users will trigger your operation and will patiently wait for it to finish. Quite often users will realize they've trigger your operation accidentally, or it is taking longer than expected and they don't want to wait for it any longer, or they just want to do something else like saving a file or shutting down the IDE, but your operations is blocking them, or... tons of other reason that may make users want to cancel your operation.

And if users cannot cancel your operation within a few seconds, they will open the Task Manager and will kill the IDE. Which is a lose-lose situation - neither your operation will be completed, nor the user will be happy. So, give the user the chance to win :-)

Code tips on improving the implementation of background operations


The most fundamental thing to make your background operations responsive for cancellation is to check if the cancellation flag has been raised. You should have already been provided with an instance of IProgressMonitor in your operation's implementation, whether it is a Job, a WorkspaceJob, a WorkspaceModifyOperation, etc. Checking for the cancellation flag is simply calling the the monitor's isCanceled() method.

The below code examples check for the cancellation flag and interrupts the operation's workflow by returning the CANCEL_STATUS.
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
Checking for the cancellation flag should be done as often as possible. This check is a cheap operation and there should not be any concerns about the performance. In the end, if you have a long running operation, it is more important for users to cancel it promptly than having it a few milliseconds faster.

Very often long running operations are processing lots of items in a loop. As the list of items may grow unpredictably long, there should be a check for cancellation inside the loop on every iteration. This ensures that the operation can be canceled promptly regardless of the number of items that are processed. See the example below:
while (hasMoreWorkToDo()) {
    // do some work
    // ...
    if (monitor.isCanceled()) return Status.CANCEL_STATUS;
}
return Status.OK_STATUS;
Another common issue with unresponsive background operations is when they execute an external process or a long I/O operation and block on it waiting to finish. Waiting on external processes or I/O operations should no be done indefinitely. You should take advantage of any API that allows waiting for a limited amount of time. This way you can wait just for a short time (e.g. one second), then check if your operation is canceled, and if not, wait again for a short time. Below is an example how to wait for an external process to finish and check if your operation is canceled at the same time.
while (!process.waitFor(1, TimeUnit.SECONDS)) {
    // process is still running
    // check if the operation has been canceled
    if (monitor.isCanceled()) {
        process.destroy();
        return Status.CANCEL_STATUS;
    }
}
Finally, some further readings I highly recommend to every Eclipse plugin developer:

14 comments:

  1. I still remember jpa tools having this issue. Horrible experience. The whole ide would be frozen and you could do nothing.

    ReplyDelete
    Replies
    1. If you still use the JPA Tools, please report this in the Eclipse Bugzilla.

      Delete
    2. I kind of a did. But just like with other eclipse subprojects it gets ignored after companies that contributed it withdraw.
      And at the moment I'm not using it.

      Delete
    3. I kind of a did. But just like with other eclipse subprojects it gets ignored after companies that contributed it withdraw.
      And at the moment I'm not using it.

      Delete
  2. Hi Kaloyan,

    thank you for pointing at this issue. :-)
    According to the lack of proper cancellation of Jobs I just added a new chapter about the right approaches for cancelling Jobs properly:

    http://www.vogella.com/tutorials/EclipseJobs/article.html#eclipsejobs_cancel

    FYI, in Eclipse Neon you can make use of the SubMonitor's new split method performs even better, because it omits the expensive isCanceled() calls if possible.

    Best regards,

    Simon

    ReplyDelete
    Replies
    1. Simon, thanks for pointing to the new API coming in Eclipse Neon. I added a reference to your tutorial at the end of the post.

      Delete
  3. Great post, although I was blissfully unaware of the site you linked to, basically a cesspool of anonymous bile. As a "retard on crystal meth", it's very sobering to see just how vicious anonymous cowards will get when given the opportunity. The site's creator/owner is not even showing his/her name, you have to go to a WHOIS search for that.

    ReplyDelete
    Replies
    1. What does anonymity change? I hate Eclipse with a burning passion of thousand raging suns, for the hundreds of hours of wasted effort and the hair lost. I loathe it with bile and rancor of a soul tortured by Eclipse's mind twisting error messages crafted with depraved ingenuity of the unnamable gods of the abyss. And my name is Glenn Matthews, from San Diego. Now what does that change? Is Eclipse any less a putrid pile of broken developer dreams now that you know my name? Is my festering contempt for it and anything bearing its name now diminished?
      And how many sites have you see that display their owner's name? Does Google proudly sport Sergey's or Larry's name in glowing neon? Does Zuckerberg plaster his name all over Facebook?

      Delete
    2. While anonymous bile can be very entertaining, I find it much more productive to engage in conversations where people are somehow accountable (in reputation, that is) for their mutterings, just like my reputation is accountable for the commits I push to Eclipse's repositories -- not quite an 'unnamable god of the abyss'.

      So, is Eclipse any less broken for you, engaging in such a conversation? Probably not (given that I expect you don't use Eclipse anymore, and certainly don't contribute to it), but at least your insights will be taken a bit more seriously by those who do.

      As for other web sites, yes, people really do care about who's behind, certainly if they're going to engage with them in any significant depth, or trust them with any personal information.

      Also, good luck with your rage.

      Delete
    3. I hope you realize I was mostly joking. But I do think there is no room for conversation left when a bug persists for a decade. You just naturally go where your time is valued.

      Delete
  4. I remember opening a bug report about this in 2006. This article is from 2016. A decade later, people still didn't learn Eclipse is an elaborate prank at best and a torture device at worst. At this point, it's no longer Eclipse's fault you're suffering - it's your own.

    Ditch the thing and get yourself IntelliJ IDEA right now. If you don't have the money to buy it, use the Community Edition. If you need Premium, and don't qualify for a free license, beg, steal or prostitute yourself to get it. Seriously, it's worth it.

    ReplyDelete
    Replies
    1. Thanks for the advice :-)

      I wonder why the JetBrains fans think Eclipse users are ignorant. Taking into account JetBrains heavy marketing, I am pretty sure anyone who does any software development is aware of JetBrains and their products, and tried them.

      Still, there are millions of users who download and use Eclipse. And this number is steadily growing over the years. And the reason is not that Eclipse is free (as in beer) - there are tons of free alternative now-a-days.

      Somehow reminds me of Apple fans...

      I switched to Eclipse 12-13 years ago. From Borland JBuilder. Back then IntelliJ IDEA already existed. I also looked at it (and several times more since then). But I've chosen Eclipse. And it has become only better since then. And I am sure it will do in the next decades.

      Yes, they are issues. Yes, some of them are really aging. And it is not a problem, or a weakness that we discussed them openly. We are an open community and this is our power.

      Keep hating...

      Delete
    2. I was, of course, joking for the most part :) I was dead serious about IDEA being worth it, though. No fandom here, just numbers.
      If a bug in any product survives for a decade, you have to not value either your time or dignity if you keep using it.

      Delete
    3. Are you telling me that your numbers are better than my numbers? :-)

      It's a matter of taste if you choose Eclipse, IDEA or anything else. I tried IDEA several times - it didn't charmed in any way.

      If you google for "I hate IntelliJ", you would find similar results like for "I hate Eclipse".

      Regarding aging bugs, if they survive for decades, it mean they are not critical. Yet they might be quite annoying, but obviously not enough for someone to invest her time/money and fix them.

      Regarding the issue described in this blog, the situation actually improved a lot over the years. I don't recall any issue in the Eclipse Platform itself anymore. Unresponsive background jobs are however left in lots of plugins extending the Eclipse Platform. This blog post was meant to catch the attention of Eclipse plugin developers, so they pay attention on this potential issue when they work on their plugins.

      By the way, there is an improvement coming in the Eclipse Platform that will catch those bad background jobs and make it really easy to report bugs to the responsible Eclipse plugins: https://mikael-barbero.tumblr.com/post/144085408850/non-cancelable-background-tasks

      I am sure that thanks to this improvement, the problem will disappear in the near future.

      Delete