IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Boost C++ Discussion :

Problème de log avec les threads et log4cxx


Sujet :

Boost C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mars 2007
    Messages : 79
    Par défaut Problème de log avec les threads et log4cxx
    Bonjour,

    J'ai développé une application multithreadée où chaque thread va lire des informations dans un fichier (un fichier par thread) toutes les 5 secondes.
    Et je me suis rendu compte qu'il y a un problème d'affichage de mes logs lorsque le fichier n'existe pas et qu'une exception est levée. En effet, les logs des threads s'affichent parfois sur la même ligne ou le contenu du message ne s'affiche pas. Ce qui me fait penser que mon code n'est pas Thread Safe.
    Dans le résultat d'execution de mon code, j'ai volontairement lancé 3 threads sur 3 fichiers qui n'existe pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    2014-01-28 21:19:42,369 ERROR [0x7fbaf6a6f700:null] - Probe Reading Failed : The Probe 'F1.txt' is not readable.
    2014-01-28 21:19:42,369 ERROR [0x7fbaf7270700:null] - Probe Reading Failed : The Probe 'F2.txt' is not readable.
    2014-01-28 21:19:42,369 ERROR [0x7fbaf626e700:null] - 
     
    2014-01-28 21:19:47,370 ERROR [0x7fbaf6a6f700:null] - 2014-01-28 21:19:47,370 ERROR [0x7fbaf626e700:null] - Unknown Probe Type : The Probe 'B1.txt' is unknown.
    2014-01-28 21:19:47,370 ERROR [0x7fbaf7270700:null] - Probe Reading Failed : The Probe 'F2.txt' is not readable.
    2014-01-28 21:19:52,370 ERROR [0x7fbaf6a6f700:null] - Probe Reading Failed : The Probe 'F1.txt' is not readable.
    2014-01-28 21:19:52,370 ERROR [0x7fbaf626e700:null] - Unknown Probe Type : The Probe 'B1.txt' is unknown.
    2014-01-28 21:19:52,370 ERROR [0x7fbaf7270700:null] - Probe Reading Failed : The Probe 'F2.txt' is not readable.
    J'utilise log4cxx pour loggger et on voit à la ligne 3 et 5 des logs vides.

    J'ai aussi utilisé le std::cout afin d'écarter log4cxx. Je n'ai pas le même résultat mais j'ai eu le même genre de comportement sur le premier affichage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Unknown Probe Type : The Probe 'B1.txt' is unknown.Probe Reading Failed : The Probe 'F1.txt' is not readable.Probe Reading Failed : The Probe 'F2.txt' is not readable.
     
     
    Unknown Probe Type : The Probe 'B1.txt' is unknown.
    Probe Reading Failed : The Probe 'F1.txt' is not readable.
    Probe Reading Failed : The Probe 'F2.txt' is not readable.
    Unknown Aquade Probe Type : The Probe 'B1.txt' is unknown.
    Probe Reading Failed : The Probe 'F2.txt' is not readable.
    Probe Reading Failed : The Probe 'F1.txt' is not readable.
    Je n'arrive pas à identifier d'où vient exactement le problème. Je me demande si ça ne vient pas de mon exception mais j'ai aucune certitude.

    Classe CustomException
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    class CustomException : public std::exception
    {
    protected:
    	/**
             * The name of the exception
             */
    	std::string m_name;
     
    	/**
             * The description of the exception
             */
    	std::string m_description;
     
    public:
    	CustomException(std::string name, std::string description) noexcept;
     
    	virtual ~CustomException();
     
    	virtual const char * what() noexcept
    	{
    		std::stringstream ss;
    		ss << m_name << " : " << m_description;
    		return ss.str().c_str();
    	}
    };
    Classe qui traite un fichier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    class CustomProcess
    {
    protected:
    	std::string m_filePath;
    public:
     
    	explicit CustomProcess(std::string filePath)
    	: m_filePath(filePath)
    	{
     
    	}
     
    	void operator()()
    	{
    		while (true)
    		{
    			try
    			{
    				try
    				{
    					getData();
    				}
    				catch(CustomException& e)
    				{
    					LOG4CXX_ERROR(classLogger, e.what());
    				}
     
    				boost::this_thread::sleep(boost::posix_time::seconds(5));
     
    				// Make sure we can be interrupted
    				boost::this_thread::interruption_point();
    			}
    			catch(const boost::thread_interrupted&)
    			{
    				LOG4CXX_INFO(classLogger, "Thread interrupted");
    				break;
    			}
    		}
    	}
     
    	void getData() throw(CustomException)
    	{
    		float value = 0.0;
     
    		if(!m_filePath.at(0) == 'F')
    		{
    			std::ifstream ifs(m_filePath);
    			if(!ifs.fail())
    			{
    				static const boost::regex temperatureRegex("([0-9a-fA-F]{2}[ ]){9}t=([0-9]+)");
     
    				std::string line;
    				while(getline(ifs, line))
    				{
    					boost::smatch match;
    					if(boost::regex_match(line, match,temperatureRegex))
    					{
    						std::string temperatureValue = std::string() + match[2];
    						value = atoi(temperatureValue.c_str());
    						value /= 1000;
    						break;
    					}
    				}
    				if(value == 0.0)
    				{
    					std::stringstream description;
    					description << "The Probe " << m_filePath << " has not a correct value.";
    					throw CustomException("Probe Reading Failed", description.str());
    				}
    			}
    			else
    			{
    				std::stringstream description;
    				description << "The Probe '" <<m_filePath << "' is not readable.";
    				throw CustomException("Probe Reading Failed", description.str());
    			}
    		}
    		else
    		{
    			std::stringstream description;
    			description << "The Probe'" << m_filePath << "' is unknown.";
    			throw CustomException("Unknown Probe Type", description.str());
    		}
     
    		...
    	}
    };
    Le main qui lance les threads
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    std::list<string> fileList= ....;
     
    boost::thread_group customProcessThreadGroup;
    std::list<string>::iterator it;
    for(it = fileList.begin(); it != fileList.end(); ++it)
    {
    	CustomProcess customProcess(*it);
    	customProcessThreadGroup.create_thread(customProcess);
    }
     
    customProcessThreadGroup.join_all();

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    Salut,

    Comme chaque thread accède en écriture au même flux, il faut locker celui-ci avant utilisation, les écritures (et les lectures) n'étant pas atomique.
    Regarde du côté des mutex et de mutex_lock.

  3. #3
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 290
    Billets dans le blog
    2
    Par défaut
    Effectivement, les flux standard ne sont pas thread safe, tu as donc de l'entrelacement.
    Je te conseilles les mutex de boost, simple et efficace. Par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <boost/thread/mutex.hpp>
     
    class MyLogger
    {
    private:
       static boost::mutex mutex_;
     
    public:
       static void MyLogError( const std::string & message )
       {
          mutex_.lock();
          LOG4CXX_ERROR(message);
          mutex_.unlock();
       }
    };

    Sinon, visiblement log4cxx est thread safe, il s'agit de bien le configurer. C'est une histoire avec l'appender apparemment, mais comme je ne connais pas cette lib je n'ai pas tout compris.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mars 2007
    Messages : 79
    Par défaut
    En utilisant un mutex, cela fonctionne correctement avec le cout.

    En revanche avec log4cxx, ça n'a rien changé sur la console avec le mutex.
    Mais je me suis rendu compte qu'avec l'appender file il n'y a pas de problème et même sans mutex. Le seul truc étrange c'est le ^@ à la place du U de Unknown.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    2014-01-29 19:20:50,096 ERROR [0x7f4706484700:null] - ^@nknown Probe Type : The Probe 'B1.txt' is unknown.
    2014-01-29 19:20:50,096 ERROR [0x7f4706c85700:null] - Probe Reading Failed : The Probe 'F1.txt' is not readable.
    2014-01-29 19:20:50,096 ERROR [0x7f4707486700:null] - Probe Reading Failed : The Probe 'F2.txt' is not readable.
    Voici pour info mon log4cxx.xml
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <?xml version="1.0" encoding="UTF-8" ?>
     <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
      <!-- Output the log message to system console.
        -->
      <appender name="appConsoleAppender" class="org.apache.log4j.ConsoleAppender">    
        <param name="Target" value="System.out"/>
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d %-5p [%t:%x] %C{2} (%F:%L) - %m%n" />
            </layout>
      </appender>
     
      <!-- Output the log message to log file
        -->
      <appender name="appFileAppender" class="org.apache.log4j.FileAppender">
        <param name="file" value="/tmp/myApplication.log" />
        <param name="append" value="true" />
        <layout class="org.apache.log4j.PatternLayout">
          <param name="ConversionPattern" value="%d %-5p [%t:%x] %C{2} (%F:%L) - %m%n" />
        </layout>
      </appender>
     
      <root>
            <priority value="all" />
            <appender-ref ref="appFileAppender"/>
            <appender-ref ref="appConsoleAppender"/>
      </root>
     </log4j:configuration>

    Je vais googliser un peu tout ça et merci pour votre aide

Discussions similaires

  1. problèmes avec les threads
    Par lukbutor dans le forum C
    Réponses: 7
    Dernier message: 03/05/2007, 00h15
  2. Problèmes avec les thread et les pointeurs
    Par raspac dans le forum POSIX
    Réponses: 2
    Dernier message: 22/10/2006, 17h35
  3. [BOOST] Problème avec les threads
    Par SOAD08 dans le forum Dev-C++
    Réponses: 7
    Dernier message: 08/10/2006, 10h23
  4. [Avis aux pros !] Problèmes de la VCL avec les threads
    Par benj63 dans le forum C++Builder
    Réponses: 3
    Dernier message: 17/02/2006, 22h38
  5. Réponses: 5
    Dernier message: 10/05/2005, 10h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo