2017-08-01 2 views
1

Parfois, lorsque j'arrête mon module Liferay (par exemple lorsque je mets une nouvelle version de son JAR dans deploy/) le module refuse de s'arrêter.Le module Liferay (bundle OSGi) reste à "Arrêt"

Alors que le module devrait aller à « Résolu » état, il reste dans le « Arrêt » état pour toujours:

OSGi lifecycle

Habituellement, il est dû à un fil non terminé quelque part, ou une connexion réseau non correctement fermé, et c'est souvent une douleur à étudier.

Ma question: Comment savoir plus efficacement quel est le problème de ce module Liferay?

Ce que j'ai essayé:

  • Dans Gogo Shell diag <module id> ne semble pas fournir des informations précieuses sur la raison pour laquelle le module refuse de quitter l'état « Arrêt ».
  • jstack sort des milliers de lignes, dont la grande majorité est en dehors du module Liferay en question. S'il y avait un moyen de montrer des informations jstack pour seulement mon module ce serait merveilleux.
+1

Utilisez-vous un activateur dans votre module? L'arrêt de l'état signifie que la méthode Activator.stop() a été appelée mais n'a pas encore été renvoyée. Un de vos threads devrait être dans cette méthode. –

+0

@ChristianSchneider: Ajout de mon ServiceActivator. –

+1

Vous êtes sur la bonne voie pour résoudre le problème avec jstack. Il a créé un vidage de thread, mais la plupart des threads ont environ 5-10 lignes. Recherchez le thread qui est beaucoup plus grand, en particulier qui a appel à la méthode ServiceActivator.stop. Ensuite, vous verrez ce qui cause l'impasse ou le long sommeil. –

Répondre

0

Tout d'abord, trouver le PID de votre serveur webapp:

ps aux | grep tomcat 

Adapter la commande si vous exécutez un autre serveur que tomcat, ou si vous avez plusieurs instances en cours d'exécution.

Ensuite, Vidage de tous les fils de ce serveur dans un fichier:

jstack 12345 > jstack.txt 

Où est le PID 12345 que vous avez trouvé dans la première étape.

Ensuite, regardez le code source de votre bundle et trouvez l'activateur de service. Il semble généralement comme ceci:

package fr.free.nrw; 

[import section] 

public class ServiceActivator implements BundleActivator { 

    private ServiceRegistration registration; 

    @Override 
    public void start(BundleContext context) throws Exception { 
     registration = context.registerService(
      MyService.class.getName(), new MyServiceImpl(), null); 
    } 

    @Override 
    public void stop(BundleContext context) throws Exception { 
     registration.unregister(); 
    } 
} 

Prenez note:

  • l'espace de noms,
  • le nom de classe,
  • le nom de la méthode d'arrêt.

Par exemple, dans l'exemple ci-dessus, ils sont fr.free.nrw, ServiceActivator et stop, et de ces trois obtenir le nom complet fr.free.nrw.ServiceActivator.stop.

Maintenant, ouvrez jstack.txt et recherchez le nom complet.Même si le fichier est des milliers de lignes, il n'y aura plus probablement être un seul coup, et qui est le fil problématique:

at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.unregister(ServiceRegistrationImpl.java:222) 
at fr.free.nrw.ServiceActivator.stop(ServiceActivator.java:30) 
at org.eclipse.osgi.internal.framework.BundleContextImpl$4.run(BundleContextImpl.java:830) 
at org.eclipse.osgi.internal.framework.BundleContextImpl$4.run(BundleContextImpl.java:1) 
at java.security.AccessController.doPrivileged(Native Method) 
at org.eclipse.osgi.internal.framework.BundleContextImpl.stop(BundleContextImpl.java:823) 

Dans ce fichier, allez jusqu'au début du paragraphe, qui sera quelque chose comme ceci:

"fileinstall-/home/nico/p/liferay/osgi/modules" #37 daemon prio=5 os_prio=0 tid=0x00007f39480e3000 nid=0x384f waiting on condition [0x00007f395d169000] 
    java.lang.Thread.State: WAITING (parking) 
    at sun.misc.Unsafe.park(Native Method) 
    - parking to wait for <0x00000000eb8defb8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) 
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 

avec cette information en main, vous connu ce genre de problème de filetage se passe, et vous serez en mesure de le résoudre avec des techniques de débogage de fil habituelles Java (12).

0

L'activateur que vous avez partagé ne devrait jamais bloquer la méthode d'arrêt. Donc, je doute que cela puisse provoquer le comportement que vous avez décrit.

+1

Cela peut être. La méthode d'arrêt de l'activateur est appelée de manière synchrone. Il désinscrit un service et provoque l'appel d'auditeurs de service synchrones (et de service trackers). Sur ServiceTracker peut être bloqué. –

+0

Ah .. intéressant. Donc la raison pourrait être un tracker de service mal écrit ou un écouteur dans un autre bundle. –

+0

Pourrait être. Je parlais sur le niveau de service de suivi, mais on peut facilement faire une erreur sur les niveaux plus élevés, aussi. Exemple: On écrit une logique métier en dormant ou en attendant dans le setter d'une référence de service (ou dans la méthode activate) d'un composant DS. Ces extraits de code sont souvent appelés sur le même thread que l'enregistrement de service car ils sont basés sur des suiveurs de service synchrones. –