dev@glassfish.java.net

Re: deployment error/thread death

From: Jan Luehe <Jan.Luehe_at_Sun.COM>
Date: Thu, 19 Apr 2007 16:48:04 -0700

Ashish Sahni wrote:

>> Hi Tim,
>> I'm glad you bring serialization up. Please see my comment inline:
>>
>> Tim Quinn wrote:
>>
>>> Hi, Jan.
>>>
>>> Really great detective work on this. I probably should have
>>> followed this more closely given that the serialization logic I
>>> added was involved.
>>>
>>> In your research into this, did you see any place that the
>>> serialization code could have protected better against something
>>> like this?
>>>
>>> Because the serialization (and deserialization) of descriptors was a
>>> performance-only enhancement, I wrote the SerializedDescriptorHelper
>>> class to catch all Throwables that emerge from the attempt to
>>> serialize. (Although without the serialized descriptor the next
>>> reload of the app would take longer, an exception during
>>> serialization would cause no functional problem.)
>>
>> The exception thrown during redployment does render the webapp
>> unusable. So in that ir does cause the functional problem. Thoughts ?
>

One explanation might be that your redeployed jruby-based webapp does
not make any attempt
to override the "BC" provider that was registered during the initial
deployment.

RubyDigest.createDigest() registers the "BC" provider as follows:

  try {
      Class c =
Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
      
java.security.Security.insertProviderAt((java.security.Provider)c.newInstance(),2);
      provider = "BC";
  } catch(Exception e) {
      provider = null;
  }

Security.insertProviderAt() checks if the given provider has been
registered, based on its name. If a provider with the same name
already exists, it returns -1, otherwise, it will return the "slot" in
which the provider was added.

In your case, the redeployed webapp will end up with the same provider and
digest classes loaded during initial deployment, so any attempt to
perform any
digest operations will fail, since the underlying webapp classloader,
which has
turned into a "zombie", will refuse to load anything.

We should make the web container more robust against the case where a
webapp registers a crypto provider and then forgets to unregister it
during undeployment. In this case, the container should unregister the
crypto provider on the webapp's behalf, by adding this code to
WebappClassLoader.stop():

    import java.security.*;


    Provider[] providers = Security.getProviders();
    if (providers != null) {
        for (Provider provider : providers) {
            if (provider.getClass().getClassLoader() == this) {
                Security.removeProvider(provider.getName());
            }
        }
    }


Jan