blob: 2271b7d390a4bd9774b60f142c03f9dda1d177e5 [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
#include "sm.h"
#include "ExSMExitHandler.h"
#include "ExSMCommon.h"
#include "ExSMGlobals.h"
#include "ExSMEvent.h"
#include "ExSMShortMessage.h"
static uint32_t ExSM_ExitHandlerCount = 0;
void ExSM_ExitHandler(void)
{
// SEAMONSTER PROJECT APR 2013
// Given that this function is an exit handler and the process is
// about to exit, there is no real need to call SM cancel or
// finalize. SM cleanup will happen when the process goes away. We
// decided to keep this function anyway because it might be a useful
// building block in the future if SM semantics change or if the
// process wants to stay alive after detaching from SM.
int rc = 0;
ExSMGlobals *smGlobals = ExSMGlobals::GetExSMGlobals();
bool smInitialized = (smGlobals ? smGlobals->getSMInitialized() : false);
EXSM_TRACE(EXSM_TRACE_EXIT,"BEGIN ExSM_ExitHandler count %d glob %p init %d",
(int) ExSM_ExitHandlerCount, smGlobals, (int) smInitialized);
// Do nothing if any of the following are true
// * this function was already called
// * SM globals is NULL
// * SM was never successfully initialized
if (ExSM_ExitHandlerCount > 0 || smGlobals == NULL || !smInitialized)
{
EXSM_TRACE(EXSM_TRACE_EXIT, "Called multiple times, nothing to do");
EXSM_TRACE(EXSM_TRACE_EXIT, "END ExSM_ExitHandler");
return;
}
ExSM_ExitHandlerCount++;
// If this is not the reader thread, send a SHUTDOWN message to the
// reader thread and wait for the reader thread to clean up
if (!pthread_equal(pthread_self(), smGlobals->getReaderThreadTID()))
{
EXSM_TRACE(EXSM_TRACE_EXIT, "Sending SHUTDOWN msg to reader");
sm_target_t target;
memset(&target, 0, sizeof(target));
target.node = smGlobals->getSQNodeNum();
target.pid = smGlobals->getMainThreadPID();
target.id = smGlobals->getExeInternalSMID();
target.tag = 0;
ExSMShortMessage m;
m.setTarget(target);
m.setNumValues(1);
m.setValue(0, (int32_t) ExSMShortMessage::SHUTDOWN);
m.send();
// Wait for reader thread to react
EXSM_TRACE(EXSM_TRACE_MAIN_THR|EXSM_TRACE_INIT, "BEGIN wait for reader");
struct timespec waitTime;
clock_gettime(CLOCK_REALTIME, &waitTime);
waitTime.tv_sec += ExSMGlobals::READER_SHUTDOWN_WAIT;
rc = pthread_mutex_lock(smGlobals->getReaderThreadStateLock());
exsm_assert_rc(rc, "pthread_mutex_lock");
// Next step is a timed wait on a condition variable until the
// reader thread is done, or until the timer expires. The reader
// thread has two states to indicate completion: DONE and
// TERMINATED_DUE_TO_ERROR.
rc = 0;
ExSMGlobals::ThreadState rstate = smGlobals->getReaderThreadState();
while (rstate != ExSMGlobals::DONE &&
rstate != ExSMGlobals::TERMINATED_DUE_TO_ERROR &&
rc == 0)
{
rc = pthread_cond_timedwait(smGlobals->getReaderThreadStateCond(),
smGlobals->getReaderThreadStateLock(),
&waitTime);
rstate = smGlobals->getReaderThreadState();
EXSM_TRACE(EXSM_TRACE_MAIN_THR|EXSM_TRACE_INIT,
"pthread_cond_timedwait returned %d reader state %s", rc,
smGlobals->getThreadStateString(rstate));
}
rc = pthread_mutex_unlock(smGlobals->getReaderThreadStateLock());
exsm_assert_rc(rc, "pthread_mutex_unlock");
EXSM_TRACE(EXSM_TRACE_MAIN_THR|EXSM_TRACE_INIT, "END wait for reader");
} // if not reader thread
// This call will cancel the special ID used for executor internal
// communcation and then call SM_finalize
ExSM_Finalize(smGlobals);
EXSM_TRACE(EXSM_TRACE_EXIT, "END ExSM_ExitHandler");
}