Avatar of Ganesh N
Ganesh N
 asked on

Static variable (Class) in the static function is getting re-initialized when called from another/shared Lib

Hi,
Facing the typical issue on the AIX compiler/linker/server.  Please check the code below.


//  say in module 1 I have class (libmod1.so)
======================================================================================
     in file  MyErrorHandlerSmptr.h
=======================================================================================       
class MyErrorHandlerSmptr
{

public:

    MyErrorHandlerSmptr (baseErrorHandler *p)
	{
		MyErrorHandler::instance().setErrorHandler(p);
	}

    ~MyErrorHandlerSmptr()
	{
	    MyErrorHandler::instance().setErrorHandler(NULL);      
	}

};

Open in new window

======================================================================================
======================================================================================
     in file  MyErrorHandler.h
=======================================================================================       
   
   
typedef enum
    {
        SUCCESS,      /**< Success */
        WARNINGS,     /**< Warning */
        ERRORS        /**< Error   */
    } MyErrorStatus;
	
class  MyErrorHandler
{
    friend class MyErrorHandlerSmptr;
	// 

private:
    MyErrorHandler()
	: errorHandler(NULL), errorStatus(SUCCESS), last_fail_value(0)
	{   
		printf("\n 11 :: default constructor ");	
		printf("\n address of the class is   --- > %p ", this );	
	}

    MyErrorHandler(const MyErrorHandler &)
	{
	 // code like constructor 
	}


    void setErrorHandler(BaseErrorHandler* handler)
	{
		printf("\n 33 : Set error handler");	
		printf("\n address of the class is   --- > %p ",(void *) this );

		errorHandler = handler;
		errorStatus = SUCCESS;
		last_fail_value = 100;

	}

    BaseErrorHandler* errorHandler;
    MyErrorStatus errorStatus;
    int last_fail_value;

public:
    static MyErrorHandler& instance()
    {
		printf("\n ## : in singleton instance");	
        static MyErrorHandler inst;
        return inst;
    }


    bool hasErrorHandler() const
    {
		printf("\n 44 : check error handler");	
		printf("\n address of the class is   --- > %p ",(void *) this );
        return errorHandler ? true:false;
    }
	
	~MyErrorHandler();
};

Open in new window


now When from Module 1. I initialize MyErrorHandlerSmptr(..) properly and MyErrorHandler class
works properly.

Now from another module say from module 2, When i check for error handler, like this.
bool ok_handler = MyErrorHandler::instance().hasErrorHandler();

Open in new window


Some how AIX calls the default constructor again from singleton instance function and saying no error handler is set.

Is there any solution, how to fix this?

Thanks in advance.
C++

Avatar of undefined
Last Comment
Ganesh N

8/22/2022 - Mon
sarabande

friend class MyErrorHandlerSmptr;

Open in new window


with the code you posted only friend class could/would be able to call the default constructor.

i don't know why the MyErrorHandler is using class baseErrorHandler. if once instance() function is called the static instance of MyErrorHandler would be instantiated, but could not used before the baseErrorHandler was set. surely this is not a good design.

Sara
Ganesh N

ASKER
Hi sarabande,
   It is a part of code from my product. I just tried to demo it.

Problem is specific to AIX compiler/linker.

friend class is used only to make sure that no one else could set the error handler. and Not calling default constructor.
So in start I have set the error handler. i.e also initialized the class.  ( Please see friend class declaration)

My main concern is that ,  When I add below line to another module,.

bool ok_handler = MyErrorHandler::instance().hasErrorHandler();

Open in new window


control calls instance function, But instead of returning me already initialized reference. It is re-initializing the
inst
and returning me reference at other location.
From same .so (DLL) file it is working as expected.

On all other OS Windows/Linux/Solaris this is working fine. Strange thing is happening only in AIX OS.  I have asked what are the compiler option(s) they have used for AIX, from my release team. They are still finding.
sarabande

bool ok_handler = MyErrorHandler::instance().hasErrorHandler();

if this uses private constructor twice, the calls were made in different modules (for example in the main executable and second in a shared object files with extension .so).

are you using fork processes?

Sara
This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23
sarabande

you could solve the issue by moving the class into a separate .so and import the class in other modules.

Sara
Ganesh N

ASKER
Hi Sara,
yes, Private constructor is used twice.
and
NO we are not using fork process.

The process is sequential, even not multithrading at that level.

  however   below line is in catch block of try/catch section and this try/catch block is in different module. Is that forking?

bool ok_handler = MyErrorHandler::instance().hasErrorHandler(); 

Open in new window


Ganesh
Ganesh N

ASKER
>> you could solve the issue by moving the class into a separate .so and import the class in other modules.

 No can not do that.
Is there nay better way than this? if I move I need to modify many other files. which are using this class.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
sarabande

Is there nay better way than this?

perhaps. since the the error handling is done by baseErrorHandler, you would need to make sure that all instances of your MyErrorHandler were using the same pointer. then in the error handling functions of baseErrorHandler you need to use a mutex if shared resources (for example the error log file) were used. thus all critical paths would run exclusively.

actually a shared error handler class most likely is the simpler way. you even could think of a daemon which does the error handling and gets ist requests by using tcp sockets.

Sara
ASKER CERTIFIED SOLUTION
Ganesh N

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
Ganesh N

ASKER
sara,
You believe it or not. Changing the name of function sorts my issue in AIX. Same code was working fine in Winows/Linux/Solaris.  we ship the product for these 4 OS. and the problem was reported by a customer to us.
I have also checked with AIX compiler option, we use xlC option .

complete code is in real time complex production env.  
Since the changing the function name would force immanence recompile in our case, we need to write a wrapper to get away and changing only at the places needed.

Thanks,
Ganesh
sarabande

Why did you object to delete the question? I can't help with closing the question as already stated.

If you can't give more information and can't do further investigation as requested by me, you should close the question by accepting your own comment with 0 points.

Sara
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Ganesh N

ASKER
Tried it in production env of my company.