0

I have written a simple program to check the ability of log4cplus apis to work perfectly in multithreading environment but when I run, it crashes all the time.

Please give some, why it is happening. I decided to use log4cplus apis because most of the review on net is saying that it is thread safe.

my test source code is given below.

#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <pthread.h>
using namespace std;

#define NUM_THREADS     5

static Logger logger;

static void log4splus_api()
{
    logger = Logger::getInstance("database");
        LOG4CPLUS_WARN(logger, "This is a short: " << (short)-100);
        LOG4CPLUS_WARN(logger, "This is a unsigned short: " << (unsigned short)100);

    logger = Logger::getInstance("network");
    LOG4CPLUS_WARN(logger, "This is a short: " << (short)-100);
        LOG4CPLUS_WARN(logger, "This is a unsigned short: " << (unsigned short)100);

    logger = Logger::getInstance("utility");
    LOG4CPLUS_WARN(logger, "This is a short: " << (short)-100);
        LOG4CPLUS_WARN(logger, "This is a unsigned short: " << (unsigned short)100);

    logger = Logger::getInstance("server");
    LOG4CPLUS_WARN(logger, "This is a short: " << (short)-100);
        LOG4CPLUS_WARN(logger, "This is a unsigned short: " << (unsigned short)100);

    logger = Logger::getInstance("upgrade");
    LOG4CPLUS_WARN(logger, "This is a short: " << (short)-100);
        LOG4CPLUS_WARN(logger, "This is a unsigned short: " << (unsigned short)100);
}

void *testThread(void *threadid)
{
   long tid;
   tid = (long)threadid;
   cout << "\ntestThread! Thread ID, " << tid << endl;

    while(true)
    {
        try
        {
            log4splus_api();
        }
        catch(...)
        {
            printf("\nException occured...");
        }
    }

   pthread_exit(NULL);
}

int main ()
{
    initialize();
    PropertyConfigurator config("./logs.properties");
    config.configure();
   pthread_t threads[NUM_THREADS];
   int rc;
   int i;
   for( i=0; i < NUM_THREADS; i++ ){
      cout << "main() : creating thread, " << i << endl;
      rc = pthread_create(&threads[i], NULL, 
                          testThread, (void *)i);
      if (rc){
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

logs.properties file is given below

### logs.properties

# root logger

log4cplus.rootLogger=INFO,STDOUT
log4cplus.appender.STDOUT=log4cplus::ConsoleAppender

# specific logger

log4cplus.logger.database=INFO, database
log4cplus.additivity.database=false

# specific logger

log4cplus.logger.network=INFO, network
log4cplus.additivity.network=false

# specific logger

log4cplus.logger.utility=INFO, utility
log4cplus.additivity.utility=false

# specific logger

log4cplus.logger.server=INFO, server
log4cplus.additivity.server=false

# specific logger

log4cplus.logger.upgrade=INFO, upgrade
log4cplus.additivity.upgrade=false


# appender that automatically rolls files

log4cplus.appender.database=log4cplus::RollingFileAppender
log4cplus.appender.database.File=database.log
log4cplus.appender.database.layout=log4cplus::PatternLayout
log4cplus.appender.database.layout.ConversionPattern=%D | %-5.5p | %-20.20c | %m|%n
log4cplus.appender.database.filters.1=log4cplus::spi::LogLevelRangeFilter
log4cplus.appender.database.filters.1.LogLevelMin=DEBUG
log4cplus.appender.database.filters.1.LogLevelMax=FATAL
log4cplus.appender.database.filters.1.AcceptOnMatch=true
log4cplus.appender.database.filters.2=log4cplus::spi::DenyAllFilter
#log4cplus.appender.database.Schedule=DAILY
#log4cplus.appender.database.Append=false
log4cplus.appender.database.MaxBackupIndex=1
log4cplus.appender.database.MaxFileSize=1000KB

# appender that automatically rolls files

log4cplus.appender.network=log4cplus::RollingFileAppender
log4cplus.appender.network.File=network.log
log4cplus.appender.network.layout=log4cplus::PatternLayout
log4cplus.appender.network.layout.ConversionPattern=%D | %-5.5p | %-20.20c | %m|%n
log4cplus.appender.network.filters.1=log4cplus::spi::LogLevelRangeFilter
log4cplus.appender.network.filters.1.LogLevelMin=DEBUG
log4cplus.appender.network.filters.1.LogLevelMax=FATAL
log4cplus.appender.network.filters.1.AcceptOnMatch=true
log4cplus.appender.network.filters.2=log4cplus::spi::DenyAllFilter
#log4cplus.appender.network.Schedule=DAILY
#log4cplus.appender.network.Append=false
log4cplus.appender.network.MaxBackupIndex=1
log4cplus.appender.network.MaxFileSize=1000KB

# appender that automatically rolls files

log4cplus.appender.utility=log4cplus::RollingFileAppender
log4cplus.appender.utility.File=utility.log
log4cplus.appender.utility.layout=log4cplus::PatternLayout
log4cplus.appender.utility.layout.ConversionPattern=%D | %-5.5p | %-20.20c | %m|%n
log4cplus.appender.utility.filters.1=log4cplus::spi::LogLevelRangeFilter
log4cplus.appender.utility.filters.1.LogLevelMin=DEBUG
log4cplus.appender.utility.filters.1.LogLevelMax=FATAL
log4cplus.appender.utility.filters.1.AcceptOnMatch=true
log4cplus.appender.utility.filters.2=log4cplus::spi::DenyAllFilter
#log4cplus.appender.utility.Schedule=DAILY
#log4cplus.appender.utility.Append=false
log4cplus.appender.utility.MaxBackupIndex=1
log4cplus.appender.utility.MaxFileSize=1000KB

# appender that automatically rolls files

log4cplus.appender.server=log4cplus::RollingFileAppender
log4cplus.appender.server.File=server.log
log4cplus.appender.server.layout=log4cplus::PatternLayout
log4cplus.appender.server.layout.ConversionPattern=%D | %-5.5p | %-20.20c | %m|%n
log4cplus.appender.server.filters.1=log4cplus::spi::LogLevelRangeFilter
log4cplus.appender.server.filters.1.LogLevelMin=DEBUG
log4cplus.appender.server.filters.1.LogLevelMax=FATAL
log4cplus.appender.server.filters.1.AcceptOnMatch=true
log4cplus.appender.server.filters.2=log4cplus::spi::DenyAllFilter
#log4cplus.appender.server.Schedule=DAILY
#log4cplus.appender.server.Append=false
log4cplus.appender.server.MaxBackupIndex=1
log4cplus.appender.server.MaxFileSize=1000KB

# appender that automatically rolls files

log4cplus.appender.upgrade=log4cplus::RollingFileAppender
log4cplus.appender.upgrade.File=upgrade.log
log4cplus.appender.upgrade.layout=log4cplus::PatternLayout
log4cplus.appender.upgrade.layout.ConversionPattern=%D | %-5.5p | %-20.20c | %m|%n
log4cplus.appender.upgrade.filters.1=log4cplus::spi::LogLevelRangeFilter
log4cplus.appender.upgrade.filters.1.LogLevelMin=DEBUG
log4cplus.appender.upgrade.filters.1.LogLevelMax=FATAL
log4cplus.appender.upgrade.filters.1.AcceptOnMatch=true
log4cplus.appender.upgrade.filters.2=log4cplus::spi::DenyAllFilter
#log4cplus.appender.upgrade.Schedule=DAILY
#log4cplus.appender.upgrade.Append=false
log4cplus.appender.upgrade.MaxBackupIndex=1
log4cplus.appender.upgrade.MaxFileSize=1000KB
user3356106
  • 31
  • 1
  • 1
  • 5
  • 2
    Well you have one global variable that is used *and shared* by all threads concurrently, without protection. Think about what will happen if one thread starts to assign to the variable, gets switched out for another thread which is in the middle of a logging call. – Some programmer dude Aug 11 '14 at 12:40

1 Answers1

0

Well you have one global variable that is used and shared by all threads concurrently, without protection. Think about what will happen if one thread starts to assign to the variable, gets switched out for another thread which is in the middle of a logging call.

Yes! logger should be auto variable in log4splus_api(), or TLS variable.

sfzhang
  • 669
  • 9
  • 18