Logo Search packages:      
Sourcecode: u++ version File versions

uAbortExit.cc

//                              -*- Mode: C++ -*- 
// 
// uC++ Version 5.0.1, Copyright (C) Peter A. Buhr 1994
// 
// uAbort.cc -- 
// 
// Author           : Peter Buhr
// Created On       : Fri Oct 26 11:54:31 1990
// Last Modified By : Peter A. Buhr
// Last Modified On : Thu Aug 12 11:22:07 2004
// Update Count     : 450
//
// This  library is free  software; you  can redistribute  it and/or  modify it
// under the terms of the GNU Lesser General Public License as published by the
// Free Software  Foundation; either  version 2.1 of  the License, or  (at your
// option) any later version.
// 
// This library is distributed in the  hope that it will be useful, but WITHOUT
// ANY  WARRANTY;  without even  the  implied  warranty  of MERCHANTABILITY  or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
// for more details.
// 
// You should  have received a  copy of the  GNU Lesser General  Public License
// along  with this library.
// 


#define __U_KERNEL__
#define __U_PROFILE__
#define __U_PROFILEABLE_ONLY__


#include <uC++.h>
#include <uProfiler.h>
//#include <uDebug.h>


#include <cstdio>
#include <cstdarg>
#include <cerrno>
#include <unistd.h>                             // _exit


void uAbortExit() {
    // Deal with any starting processors spinning to get onto the global
    // processor list.

    uKernelModule::uGlobalProcessorLock->acquire();   // never released again
    uKernelModule::uGlobalSpinAbort = true;

    // Destory any remaining processors.

    uProcessorDL *pr;
    for ( uSeqGen<uProcessorDL> gen(*uKernelModule::uGlobalProcessors); gen >> pr; ) {
      if ( &(pr->uGet()) != &uThisProcessor() ) {     // do not kill current processor
#ifdef __U_DEBUG_H__
          fprintf( stderr, "uAbortExit(), killing process 0x%p %d\n", &(pr->uGet()), pr->uGet().uGetPid() );
#endif // __U_DEBUG_H__
          kill( pr->uGet().uGetPid(), SIGKILL );
      } // if
    } // for
} // uAbortExit


void uExit( int retcode ) {
    uKernelModule::uGlobalAbort = true;

#if defined( __U_MULTI__ ) && ! defined( __solaris__ )      // all SUN lwps are terminated by exit/abort
    // Only the root processor can return a value to the shell so it is
    // necessary to migrate to the sustem processor to exit with a return code.
    // Also uExit is not called in the kernal because it blocks.

    uKernelModule::uSystemProcessor->uProcExit( retcode );
    // CONTROL NEVER REACHES HERE!
#else
    // _exit is called instead of exit so the global destructors are not
    // called.  Trying to execute the global destructors after the processors
    // have been killed just generates incomprehensible errors.

    _exit( retcode );
#endif
} // uExit


// Only one processor should call abort and succeed.  Once a processor calls
// abort, all other processors quietly exit while the aborting processor cleans
// up the system and possibly dumps core.

void uAbort( const char *fmt, ... ) {
    uBaseTask &t = uThisTask();                       // optimization
    uKernelModule::uGlobalAbort = true;

    // uAbort cannot be recursively entered by the same or different processors
    // because all signal handlers return when the uGlobalAbort flag is true.
#if defined( __U_MULTI__ )
    if ( ! uKernelModule::uGlobalAbortLock->tryacquire() ) { // not the first task to abort ?
      sigset_t mask;
      sigemptyset( &mask );
      sigaddset( &mask, SIGALRM );              // block SIGALRM signals
      sigsuspend( &mask );                      // block the processor to prevent further damage during abort
      _exit( -1 );                              // if processor unblocks before it is killed, terminate it
    } // if
#endif // __U_MULTI__

    // profiling

    t.uProfileInactivate();                     // make sure the profiler is not called from this point on

    // Display the relevant shut down information.

    fprintf( stderr, "uC++ Runtime error (UNIX pid:%ld) ", (long int)getpid() ); // use UNIX pid (versus uGetPid)
    va_list args;
    va_start( args, fmt );
    vfprintf( stderr, fmt, args );
    va_end( args );

    fprintf( stderr, "\nError occurred while executing task %.256s (0x%p)", t.uGetName(), &t );
    if ( &t != &uThisCoroutine() ) {
      fprintf( stderr, " in coroutine %.256s (0x%p).\n", uThisCoroutine().uGetName(), &uThisCoroutine() );
    } else {
      fprintf( stderr, ".\n" );
    } // if

    // In profiling mode, output information about the current task's call stack.

    t.uPrintCallStack();

    // In debugger mode, tell the global debugger to stop the application.

#if __U_LOCALDEBUGGER_H__
    if ( ! THREAD_GETMEM( uDisableInt ) && ! THREAD_GETMEM( uDisableIntSpin ) ) {
      if ( uLocalDebugger::uLocalDebuggerActive ) uLocalDebugger::uLocalDebuggerInstance->abortApplication();
    } // if
#endif // __U_LOCALDEBUGGER_H__

    // Try to shut down other processors.

#if defined( __U_MULTI__ ) && ! defined( __solaris__ )      // all SUN lwps are terminated by exit/abort
    uAbortExit();                         // shut down other processors
#endif

    // After having killed off the other processors, dump core if required,
    // otherwise, quietly call "_exit". Cannot call "exit" because of global
    // destructors.

    if ( ! uKernelModule::uCoreDumped ) {       // child process may have failed and dumped core already
      uKernelModule::uCoreDumped = true;        // prevent other UNIX processes from dumping core
      // Use getpid (versus uGetPid) to terminate the process group.
      kill( getpid(), SIGABRT );                // "abort()" may call "raise(SIGABRT)" to NPTL thread
    } // if

    _exit( -1 );
} // uAbort


// Local Variables: //
// compile-command: "gmake install" //
// End: //

Generated by  Doxygen 1.6.0   Back to index