package cpw.mods.fml.relauncher;

import java.security.Permission;

/**
 * A custom security manager stopping certain events from happening
 * unexpectedly.
 *
 * @author cpw
 *
 */
public class FMLSecurityManager extends SecurityManager {
    @Override
    public void checkPermission(Permission perm)
    {
        String permName = perm.getName() != null ? perm.getName() : "missing";
        if (permName.startsWith("exitVM"))
        {
            String callingClass = getClassContext()[4].getName();
            // FML is allowed to call system exit
            if (!callingClass.startsWith("cpw.mods.fml."))
            {
                throw new ExitTrappedException();
            }
        }
        else if ("setSecurityManager".equals(permName))
        {
            throw new SecurityException("Cannot replace the FML security manager");
        }
        return;
    }

    public static class ExitTrappedException extends SecurityException {
        private static final long serialVersionUID = 1L;
    }
}

@@ -450,34 +450,215 @@
     
-String callingClass = getC
+Class%3C?%3E%5B%5D classContexts = getClassContext();%0A            String callingClass = classContexts.length %3E 3 ? classContexts%5B4%5D.getName() : %22none%22;%0A            String callingParent = classContexts.length %3E 4 ? c
 lass
@@ -668,12 +668,11 @@
 text
-()%5B4
+s%5B5
 %5D.ge
@@ -678,16 +678,25 @@
 etName()
+ : %22none%22
 ;%0A      
@@ -738,16 +738,64 @@
 tem exit
+ and the Minecraft applet (from the quit button)
 %0A       
@@ -804,16 +804,17 @@
    if (!
+(
 callingC
@@ -845,16 +845,274 @@
 s.fml.%22)
+ %7C%7C ( %22net.minecraft.client.Minecraft%22.equals(callingClass) && %22net.minecraft.client.Minecraft%22.equals(callingParent)) %7C%7C (%22net.minecraft.server.dedicated.DedicatedServer%22.equals(callingClass) && %22net.minecraft.server.MinecraftServer%22.equals(callingParent)))
 )%0A      

Fix up other exit points. Should stop process hangs for clean exits.