EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: RE: R3.14.8 Status/logClient patch
From: "Jeff Hill" <[email protected]>
To: <[email protected]>
Cc: "'EPICS core-talk'" <[email protected]>
Date: Wed, 23 Nov 2005 16:47:26 -0700

> -----Original Message-----
> From: Benjamin Franksen [mailto:[email protected]]
> Sent: Wednesday, November 23, 2005 5:14 AM
> To: Jeff Hill
> Subject: Re: R3.14.8 Status/logClient patch
> 
> Jeff,
> 
> I am thinking about exporting logClientDestroy (or something similar) to
> user code. Currently it is a private routine and only executed on exit
> (via epicsAtExit). I wonder what teh idea was behind the following code
> (in your original version of logClientDestroy()):
> 
>     /*
>      * mutex on (and left on)
>      */
>     epicsMutexMustLock (pClient->mutex);
>     logClientRestart (pClient);
>     epicsMutexDestroy (pClient->mutex);
>     free (pClient);
> 
> Note that logClientRestart signals the restartThread to run, which will
> eventually call mutexLock.

In the past we were well aware that vxWorks mutex semaphores could be locked
repeatedly (recursively) by the same thread. I believe that this practice
persists in R3.14 and that all implementations of epicsMutex accommodate
that behavior. 

I don't think that locking mutexes recursively is a positive thing to do.
This issue is one of the compelling reasons to manage mutexes with a guard
class.

Nevertheless, the above code would probably mostly work correctly.

> 
> Does that mean when the restartThread calls mutexLock the next time it
> gets (somehow) shut down automatically? Or does it mean that the thread
> will hang waiting for the mutex? The Developer's Guide doesn't specify
> what mutexLock does if the mutex has been destroyed.

In this situation the old code already owned the logClientGlobalMutex so the
restart thread isn't touching anything important when this is running.

It is very OS dependent what must be done to interrupt a thread that is
blocking in a socket function. On POSIX, signals generally work. Some
systems allow this to be done with shutdown. Others (vxWorks, perhaps old
vxWorks, and windows) require that the socket be closed!

I suspect that I was thinking that by taking the lock the code is preventing
some thread from happening to be within logClientSendMessageInternal (and
potentially calling flush). This would prevent problems with closing the
socket while the client was blocking in a socket function. 

However, the best way to prevent that would be to make certain that no code
has a handle to the log client data structure prior to destroying it. 

It gets worse. The problem is that some thread might be stuck in socket
send() attempting to force a flush to a stalled out log server (or network).
You are calling send() directly from within logClientSend(). 

We must call epicsSocketSystemCallInterruptMechanismQuery (see osiSock.h) to
determine what method must be used and proceed accordingly. BTW, this
function was not called epicsInterruptBlockingSocketCall() because one of
the options is close-the-socket and I didn't think that the socket should be
closed by any code other than the one that opened it, and especially not
conditionally, for good architectural reasons.

So its ok to export a log client destroy, but the creator of the log client
must be certain that all of its satellite threads are no-longer using the
log client (or blocked sending to its server) before it is destroyed. 

> 
> (The latter would of course be bad if logClientDestroy is called
> explicitly by user code, but it might be the right thing to do on
> exit.)
> 
> In my (latest) version I have replaced the above call to
> logClientRestart by logClientClose (which does not send a signal to the
> restart thread). But I am no longer sure this is correct.
> 
> Any hints appreciated.

Ok, switching back to the most recent logClient.c.

Its very complicated to have orderly shutdown for more than one thread stuck
in socket send(). Furthermore, I don't think that you want any possibility
of two threads interleaving two large messages (do we really trust what will
occur in any given OS if two threads call send at the same time)?

Therefore, I would take the send() call out of logClientSend altogether.
Instead, I would have logClientSend dump the mesasage into the buffer and
only call send from the restart (really reconnect/flush) thread every nnn
seconds. That should also be a lot nicer to the network I am thinking.
Should the buffer be full, you will need to force logClientSend to block
until the restart (really reconnect/flush) thread completes a flush (or
aborts).

What will need to occur of course in a logClientDestroy call is to set a
flag commanding the restart (really reconnect/flush) thread to shutdown,
wake it up, interrupt it if it is blocking in send, and block for it to
shutdown. This would of course also cause any threads stuck in logClientSend
to fail out.

The C++ thread management class in epicsThread.h helps some with blocking
for a thread to exit, but it's certainly easy enough to do this in C.
Usually you end up with one epicsEvent that wakes up the restart thread and
another independent epicsEvent that tells destroy that the restart thread
has shutdown.

After that we can destroy the socket, the mutex, free the memory etc.

Whew!

> 
> Cheers,
> Ben

We are soon off to eat Turkey on Thursday and Friday here. 

Have a good week/weekend. I will be back in on Monday,

Jeff



Replies:
Re: R3.14.8 Status/logClient patch Benjamin Franksen

Navigate by Date:
Prev: RE: R3.14.8 makeBaseApp.pl Jeff Hill
Next: Re: R3.14.8 Status/logClient patch Benjamin Franksen
Index: 2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: R3.14.8 Status/logClient patch Benjamin Franksen
Next: Re: R3.14.8 Status/logClient patch Benjamin Franksen
Index: 2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 02 Feb 2012 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·