I don't quite understand your answer. I did not want to keep persistent IO across web app instances, I wanted to open the IO in contextInitialized and close it in contextDestroyed. The IO stream was indeed a static variable. Could it make any problem if the IO is presumably closed/reopened on app restart?

I changed the code so that Notifier is now an object constructed in contextInitialized, and accessed within the app using ServletContext. The code of the listener is now as follows:

    public void contextInitialized(ServletContextEvent event) {
        try {
            Notifier notifier = new Notifier("bin/event_handler");
            event.getServletContext().setAttribute(Notifier.CONTEXT_ATTRIBUTE, notifier);
        } catch(IOException e) {
            System.out.println("Could not initialize notifier: " + e.toString());
    public void contextDestroyed(ServletContextEvent event) {
        Notifier notifier = (Notifier)event.getServletContext().

I am not sure about using servletContext.getAttribute() from within contextDestroyed(), but it seemed to work.

Yet, the problem is the same -- writing to the output stream is fine but in the notifier.shutdown() method. I got IOException: Broken pipe again.

Here is the backtrace you asked for:

Stack trace: java.io.IOException: Broken pipe
        at java.io.FileOutputStream.writeBytes(Native Method)
        at java.io.FileOutputStream.write(FileOutputStream.java:260)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
        at events.Notifier.notify(Notifier.java:450)
        at events.Notifier.shutdown(Notifier.java:369)
        at events.NotifierHandler.contextDestroyed(NotifierHandler.java:37)
        at winstone.WebAppConfiguration.destroy(WebAppConfiguration.java:1136)
        at winstone.HostConfiguration.destroyWebApp(HostConfiguration.java:141)        at winstone.HostConfiguration.destroy(HostConfiguration.java:149)
        at winstone.HostGroup.destroy(HostGroup.java:75)
        at winstone.Launcher.shutdown(Launcher.java:345)
        at winstone.ShutdownHook.run(ShutdownHook.java:24)

If this is not enough and you were so kind to test the war file, I might send it to you.