Hello,

it looks like your application opens several ports for RMI communication.
One class is mentioned in your first mail: ShopdbCacheSynchronizer

Maybe you can ask the developer guys to check whether these threads / ports are 
terminated / closed cleanly on shutdown event.
Quite often developers don't care much about shutting down their stuff cleanly.

Greetings,
Thomas

-----Ursprüngliche Nachricht-----
Von: Simon Matter <simon.mat...@invoca.ch> 
Gesendet: Dienstag, 30. November 2021 15:40
An: Tomcat Users List <users@tomcat.apache.org>
Betreff: Re: Tomcat 9 doesn't shutdown cleanly

Hi Chris,

Thank you for the quick reply.

> Simon,
>
> On 11/30/21 08:21, Simon Matter wrote:
>> I'm running an application on Tomcat 9.0.55 on x86_64 Linux with 
>> OpenJDK
>> JRE-11.0.13+8 and have problems shutting down Tomcat in certain ways.
>>
>> When I shutdown Tomcat via 'catalina.sh stop', it shuts down mostly 
>> (most threads are gone) but send a thread dump to catalina.out and is 
>> later killer by an OS signal.
>
> This should only happen if you have CATALINA_PID defined. Are you 
> indeed defining that environment variable?
>
> catalina.sh has this code in it, which is probably what you are seeing:
>
>            echo "To aid diagnostics a thread dump has been written to 
> standard out."
>            kill -3 `cat "$CATALINA_PID"`
>

That's true, I have CATALINA_PID defined when the call of "catalina.sh start" 
is done. So yes, the script will kill the java process if it doesn't terminate.

>> When shutting down Tomcat via the shutdown listener on port 8005, it 
>> also shuts down mostly but without the thread dump in catalina.out. 
>> Sending SIGTERM later to the still running java process terminates 
>> it.
>
> Right: when you manually connect to the shutdown port and send 
> "SHUTDOWN" (or whatever), it asks Tomcat to shut down but doesn't send 
> a signal. You have to do that manually, too.

On a test host, when I send "SHUTDOWN" to the shutdown listener, Tomcat shuts 
down and the Java VM terminates.

Only on this host with the application, when I send "SHUTDOWN" to the shutdown 
listener, Tomcat shuts down but the Java VM doesn't terminate.

>
>> So both methods somehow terminate Tomcat partly but not completely.
>
> You have one or two of the following issues:
>
> 1. You have a non-daemon thread running 2. You have an unusually long 
> shutdown process that just takes "too long"
>
> The good news is that the thread-dup can answer that question: what's 
> in the thread dump that is generated when you run "catalina.sh stop"?
>
>> When simply sending SIGTERM on the OS level, Tomcat shuts down 
>> cleanly and terminates without issues.
>>
>> One thing in common is that I always see these messages while 
>> shutting
>> down:
>>
>> 30-Nov-2021 13:59:36.985 SEVERE [main] 
>> org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesRmiTa
>> rgets Found RMI Target with stub class class 
>> [sun.rmi.registry.RegistryImpl_Stub] and value 
>> [RegistryImpl_Stub[UnicastRef [liveRef:
>> [endpoint:[157.161.91.47:2071](local),objID:[0:0:0, 0]]]]]. This RMI 
>> Target has been forcibly removed to prevent a memory leak.
>> 30-Nov-2021 13:59:36.987 SEVERE [main] 
>> org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesRmiTa
>> rgets Found RMI Target with stub class class [com.sun.proxy.$Proxy51] 
>> and value 
>> [Proxy[ShopdbCacheSynchronizer,RemoteObjectInvocationHandler[UnicastR
>> ef
>> [liveRef:
>> [endpoint:[157.161.91.47:1096](local),objID:[-6f4b2f9d:17d70eb1ef4:-7
>> ffd, -4005526521234186948]]]]]]. This RMI Target has been forcibly 
>> removed to prevent a memory leak.
>> 30-Nov-2021 13:59:36.987 SEVERE [main] 
>> org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesRmiTa
>> rgets Found RMI Target with stub class class 
>> [sun.rmi.registry.RegistryImpl_Stub] and value 
>> [RegistryImpl_Stub[UnicastRef [liveRef:
>> [endpoint:[157.161.91.47:1096](local),objID:[0:0:0, 0]]]]]. This RMI 
>> Target has been forcibly removed to prevent a memory leak.
>>
>> Why do the three methods to shutdown Tomcat differ and how can I make 
>> 'catalina.sh stop' or the shutdown listener work the same way like 
>> sending the OS signal.
>
> What's the difference? You don't want the thread dump in your 
> catalina.out? That's supposed to be helpful in debugging why your 
> shutdown isn't clean. It sounds like you are saying "help me with my 
> unclean shutdown; please get rid of the debugging information that is 
> trying to help me!".
>
>> I've tried, beside a lot of other things, to set 
>> skipMemoryLeakChecksOnJvmShutdown="true" in context.xml but it seems 
>> to change nothing at all.
>
> Tomcat will never kill your non-daemon thread(s) from inside the VM.
> Since you are using a CATALINA_PID environment variable (and, 
> therefore, a pid-file), the shutdown process is sending the TERM 
> signal. It's also possibly sending a KILL signal, depending on whether 
> or not the TERM worked and if -force was supplied on the command-line.

Unfortunately I am not an insider when it comes to Java, so I'm not sure what a 
non-daemon thread means here? Can these be threads started by our application 
which are non-daemon threads? So they will be terminated with SIGTERM to the 
Java VM but not using the shutdown listener?

I'll paste a thread dump below.

Thanks,
Simon

Full thread dump OpenJDK 64-Bit Server VM (11.0.13+8 mixed mode):

Threads class SMR info:
_java_thread_list=0x000055a49ac4ba60, length=18, elements={ 0x00007f1ac0148800, 
0x00007f1ac014a800, 0x00007f1ac015f800, 0x00007f1ac0161800, 0x00007f1ac0164000, 
0x00007f1ac0168800, 0x00007f1ac016a000, 0x00007f1ac01ad800, 0x00007f1ac0258000, 
0x00007f1ac0311000, 0x00007f1ac0318000, 0x00007f1ac031a000, 0x00007f1ac25d6800, 
0x00007f1ac25fe800, 0x00007f1ac2600000, 0x00007f1ac1dd9000, 0x00007f1a68809000, 
0x00007f1ac2111800 }

"Reference Handler" #2 daemon prio=10 os_prio=0 cpu=15.74ms elapsed=565.65s 
tid=0x00007f1ac0148800 nid=0x7509 waiting on condition [0x00007f1aa81f4000]
   java.lang.Thread.State: RUNNABLE
        at
java.lang.ref.Reference.waitForReferencePendingList(java.base@11.0.13/Native
Method)
        at
java.lang.ref.Reference.processPendingReferences(java.base@11.0.13/Unknown
Source)
        at
java.lang.ref.Reference$ReferenceHandler.run(java.base@11.0.13/Unknown
Source)

"Finalizer" #3 daemon prio=8 os_prio=0 cpu=17.20ms elapsed=565.65s
tid=0x00007f1ac014a800 nid=0x750a in Object.wait()  [0x00007f1aa17b5000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(java.base@11.0.13/Native Method)
        - waiting on <no object reference available>
        at java.lang.ref.ReferenceQueue.remove(java.base@11.0.13/Unknown
Source)
        - waiting to re-lock in wait() <0x0000000082f45e68> (a
java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(java.base@11.0.13/Unknown
Source)
        at
java.lang.ref.Finalizer$FinalizerThread.run(java.base@11.0.13/Unknown
Source)

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 cpu=0.18ms elapsed=565.63s
tid=0x00007f1ac015f800 nid=0x750b waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Service Thread" #5 daemon prio=9 os_prio=0 cpu=0.06ms elapsed=565.63s
tid=0x00007f1ac0161800 nid=0x750c runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #6 daemon prio=9 os_prio=0 cpu=55607.79ms elapsed=565.63s 
tid=0x00007f1ac0164000 nid=0x750d waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   No compile task

"C1 CompilerThread0" #7 daemon prio=9 os_prio=0 cpu=8101.56ms elapsed=565.63s 
tid=0x00007f1ac0168800 nid=0x750e waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   No compile task

"Sweeper thread" #8 daemon prio=9 os_prio=0 cpu=149.89ms elapsed=565.63s
tid=0x00007f1ac016a000 nid=0x750f runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Common-Cleaner" #9 daemon prio=8 os_prio=0 cpu=10.97ms elapsed=565.56s
tid=0x00007f1ac01ad800 nid=0x7510 in Object.wait()  [0x00007f1aa11af000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(java.base@11.0.13/Native Method)
        - waiting on <no object reference available>
        at java.lang.ref.ReferenceQueue.remove(java.base@11.0.13/Unknown
Source)
        - waiting to re-lock in wait() <0x0000000082f55120> (a
java.lang.ref.ReferenceQueue$Lock)
        at jdk.internal.ref.CleanerImpl.run(java.base@11.0.13/Unknown Source)
        at java.lang.Thread.run(java.base@11.0.13/Unknown Source)
        at jdk.internal.misc.InnocuousThread.run(java.base@11.0.13/Unknown
Source)

"AsyncFileHandlerWriter-1419810764" #12 daemon prio=5 os_prio=0 cpu=61.46ms 
elapsed=565.37s tid=0x00007f1ac0258000 nid=0x7511 waiting on condition  
[0x00007f1aa0c86000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at jdk.internal.misc.Unsafe.park(java.base@11.0.13/Native Method)
        - parking to wait for  <0x0000000083033b90> (a
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at
java.util.concurrent.locks.LockSupport.parkNanos(java.base@11.0.13/Unknown
Source)
        at
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(java.base@11.0.13/Unknown
Source)
        at
java.util.concurrent.LinkedBlockingDeque.pollFirst(java.base@11.0.13/Unknown
Source)
        at
java.util.concurrent.LinkedBlockingDeque.poll(java.base@11.0.13/Unknown
Source)
        at
org.apache.juli.AsyncFileHandler$LoggerThread.run(AsyncFileHandler.java:159)

"RMI TCP Accept-1198" #13 daemon prio=5 os_prio=0 cpu=0.62ms elapsed=564.60s 
tid=0x00007f1ac0311000 nid=0x7517 runnable [0x00007f1aa0174000]
   java.lang.Thread.State: RUNNABLE
        at java.net.PlainSocketImpl.socketAccept(java.base@11.0.13/Native
Method)
        at
java.net.AbstractPlainSocketImpl.accept(java.base@11.0.13/Unknown
Source)
        at java.net.ServerSocket.implAccept(java.base@11.0.13/Unknown Source)
        at java.net.ServerSocket.accept(java.base@11.0.13/Unknown Source)
        at
sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(java.rmi@11.0.13/Unknown
Source)
        at
sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(java.rmi@11.0.13/Unknown
Source)
        at java.lang.Thread.run(java.base@11.0.13/Unknown Source)

"RMI TCP Accept-1199" #14 daemon prio=5 os_prio=0 cpu=0.20ms elapsed=564.59s 
tid=0x00007f1ac0318000 nid=0x7518 runnable [0x00007f1a99dfe000]
   java.lang.Thread.State: RUNNABLE
        at java.net.PlainSocketImpl.socketAccept(java.base@11.0.13/Native
Method)
        at
java.net.AbstractPlainSocketImpl.accept(java.base@11.0.13/Unknown
Source)
        at java.net.ServerSocket.implAccept(java.base@11.0.13/Unknown Source)
        at java.net.ServerSocket.accept(java.base@11.0.13/Unknown Source)
        at
sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(java.rmi@11.0.13/Unknown
Source)
        at
sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(java.rmi@11.0.13/Unknown
Source)
        at java.lang.Thread.run(java.base@11.0.13/Unknown Source)

"RMI TCP Accept-0" #15 daemon prio=5 os_prio=0 cpu=0.16ms elapsed=564.53s
tid=0x00007f1ac031a000 nid=0x7519 runnable  [0x00007f1a99cfd000]
   java.lang.Thread.State: RUNNABLE
        at java.net.PlainSocketImpl.socketAccept(java.base@11.0.13/Native
Method)
        at
java.net.AbstractPlainSocketImpl.accept(java.base@11.0.13/Unknown
Source)
        at java.net.ServerSocket.implAccept(java.base@11.0.13/Unknown Source)
        at java.net.ServerSocket.accept(java.base@11.0.13/Unknown Source)
        at
sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(jdk.management.agent@11.0.13/Unknown
Source)
        at
sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(java.rmi@11.0.13/Unknown
Source)
        at
sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(java.rmi@11.0.13/Unknown
Source)
        at java.lang.Thread.run(java.base@11.0.13/Unknown Source)

"RMI TCP Accept-1096" #20 daemon prio=5 os_prio=0 cpu=0.45ms elapsed=524.39s 
tid=0x00007f1ac25d6800 nid=0x75a2 runnable [0x00007f1a7964d000]
   java.lang.Thread.State: RUNNABLE
        at java.net.PlainSocketImpl.socketAccept(java.base@11.0.13/Native
Method)
        at
java.net.AbstractPlainSocketImpl.accept(java.base@11.0.13/Unknown
Source)
        at java.net.ServerSocket.implAccept(java.base@11.0.13/Unknown Source)
        at java.net.ServerSocket.accept(java.base@11.0.13/Unknown Source)
        at
sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(java.rmi@11.0.13/Unknown
Source)
        at
sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(java.rmi@11.0.13/Unknown
Source)
        at java.lang.Thread.run(java.base@11.0.13/Unknown Source)

"RMI Reaper" #21 prio=5 os_prio=0 cpu=0.40ms elapsed=524.33s
tid=0x00007f1ac25fe800 nid=0x75a3 in Object.wait()  [0x00007f1a7954c000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(java.base@11.0.13/Native Method)
        - waiting on <0x000000008308a268> (a
java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(java.base@11.0.13/Unknown
Source)
        - waiting to re-lock in wait() <0x000000008308a268> (a
java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(java.base@11.0.13/Unknown
Source)
        at
sun.rmi.transport.ObjectTable$Reaper.run(java.rmi@11.0.13/Unknown
Source)
        at java.lang.Thread.run(java.base@11.0.13/Unknown Source)

"RMI GC Daemon" #22 daemon prio=2 os_prio=0 cpu=0.56ms elapsed=524.33s
tid=0x00007f1ac2600000 nid=0x75a4 in Object.wait()  [0x00007f1a79249000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(java.base@11.0.13/Native Method)
        - waiting on <0x0000000083f674b8> (a
sun.rmi.transport.GC$LatencyLock)
        at sun.rmi.transport.GC$Daemon.run(java.rmi@11.0.13/Unknown Source)
        - waiting to re-lock in wait() <0x0000000083f674b8> (a
sun.rmi.transport.GC$LatencyLock)
        at java.lang.Thread.run(java.base@11.0.13/Unknown Source)
        at jdk.internal.misc.InnocuousThread.run(java.base@11.0.13/Unknown
Source)

"RMI TCP Accept-2071" #24 daemon prio=5 os_prio=0 cpu=0.50ms elapsed=516.66s 
tid=0x00007f1ac1dd9000 nid=0x75b4 runnable [0x00007f1a7994e000]
   java.lang.Thread.State: RUNNABLE
        at java.net.PlainSocketImpl.socketAccept(java.base@11.0.13/Native
Method)
        at
java.net.AbstractPlainSocketImpl.accept(java.base@11.0.13/Unknown
Source)
        at java.net.ServerSocket.implAccept(java.base@11.0.13/Unknown Source)
        at java.net.ServerSocket.accept(java.base@11.0.13/Unknown Source)
        at
sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(java.rmi@11.0.13/Unknown
Source)
        at
sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(java.rmi@11.0.13/Unknown
Source)
        at java.lang.Thread.run(java.base@11.0.13/Unknown Source)

"process reaper" #154 daemon prio=10 os_prio=0 cpu=1.19ms elapsed=7.35s
tid=0x00007f1a68809000 nid=0x7b02 waiting on condition [0x00007f1aa80f3000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at jdk.internal.misc.Unsafe.park(java.base@11.0.13/Native Method)
        - parking to wait for  <0x000000008d084b78> (a
java.util.concurrent.SynchronousQueue$TransferStack)
        at
java.util.concurrent.locks.LockSupport.parkNanos(java.base@11.0.13/Unknown
Source)
        at
java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(java.base@11.0.13/Unknown
Source)
        at
java.util.concurrent.SynchronousQueue$TransferStack.transfer(java.base@11.0.13/Unknown
Source)
        at
java.util.concurrent.SynchronousQueue.poll(java.base@11.0.13/Unknown
Source)
        at
java.util.concurrent.ThreadPoolExecutor.getTask(java.base@11.0.13/Unknown
Source)
        at
java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@11.0.13/Unknown
Source)
        at
java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@11.0.13/Unknown
Source)
        at java.lang.Thread.run(java.base@11.0.13/Unknown Source)

"DestroyJavaVM" #162 prio=5 os_prio=0 cpu=38702.67ms elapsed=3.50s
tid=0x00007f1ac2111800 nid=0x74fd waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"VM Thread" os_prio=0 cpu=410.18ms elapsed=565.66s tid=0x00007f1ac0140000
nid=0x7508 runnable

"GC Thread#0" os_prio=0 cpu=3200.32ms elapsed=565.68s
tid=0x00007f1ac0040000 nid=0x74ff runnable

"GC Thread#1" os_prio=0 cpu=3191.55ms elapsed=564.64s
tid=0x00007f1a8c001000 nid=0x7515 runnable

"G1 Main Marker" os_prio=0 cpu=5.91ms elapsed=565.68s
tid=0x00007f1ac0071800 nid=0x7500 runnable

"G1 Conc#0" os_prio=0 cpu=3307.29ms elapsed=565.68s tid=0x00007f1ac0073800
nid=0x7501 runnable

"G1 Refine#0" os_prio=0 cpu=304.37ms elapsed=565.68s
tid=0x00007f1ac00e5800 nid=0x7502 runnable

"G1 Refine#1" os_prio=0 cpu=0.11ms elapsed=564.63s tid=0x00007f1a90001000
nid=0x7516 runnable

"G1 Young RemSet Sampling" os_prio=0 cpu=173.47ms elapsed=565.68s
tid=0x00007f1ac00e7800 nid=0x7503 runnable "VM Periodic Task Thread" os_prio=0 
cpu=353.71ms elapsed=564.52s
tid=0x00007f1ac032b800 nid=0x751a waiting on condition

JNI global refs: 19, weak refs: 0

Heap
 garbage-first heap   total 716800K, used 312709K [0x0000000082e00000,
0x0000000100000000)
  region size 1024K, 35 young (35840K), 5 survivors (5120K)
 Metaspace       used 97218K, capacity 99705K, committed 99788K, reserved
1132544K
  class space    used 14830K, capacity 15794K, committed 15820K, reserved
1048576K






---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to