OW_PlatformSignal.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * Copyright (C) 2005 Vintela, Inc. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions are met:
00006  *
00007  *  - Redistributions of source code must retain the above copyright notice,
00008  *    this list of conditions and the following disclaimer.
00009  *
00010  *  - Redistributions in binary form must reproduce the above copyright notice,
00011  *    this list of conditions and the following disclaimer in the documentation
00012  *    and/or other materials provided with the distribution.
00013  *
00014  *  - Neither the name of Vintela, Inc. nor the names of its
00015  *    contributors may be used to endorse or promote products derived from this
00016  *    software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028  * POSSIBILITY OF SUCH DAMAGE.
00029  *******************************************************************************/
00030 
00035 #include "OW_Platform.hpp"
00036 #include "OW_PlatformSignal.hpp"
00037 #include "OW_UserUtils.hpp"
00038 #include <ostream>
00039 
00040 namespace OW_NAMESPACE
00041 {
00042    namespace Platform
00043    {
00044       namespace Signal
00045       {
00046          SignalInformation::SignalInformation() :
00047             signalAction(0),
00048             signalNumber(0),
00049             errorNumber(0),
00050             signalCode(0),
00051             originatingPID(0),
00052             originatingUID(0),
00053             faultAddress(0),
00054             fileDescriptor(0),
00055             band(0)
00056          {
00057 #if defined(OW_HAVE_SIGVAL_TYPE_SIGVAL_INT)
00058             timerValue.sigval_int = 0;
00059 #elif defined(OW_HAVE_SIGVAL_TYPE_SIVAL_INT)
00060             timerValue.sival_int = 0;
00061 #else
00062             timerValue = 0;
00063 #endif
00064          }
00065 
00066          void extractSignalInformation(const siginfo_t& source, SignalInformation& dest)
00067          {
00068             // Clear out everything.
00069             dest = SignalInformation();
00070 
00071 #ifndef OW_WIN32
00072             // These three are the only ones guaranteed to always be set in the
00073             // struct.  Everything else may be set, depending on the values for
00074             // these three fields.
00075             dest.signalNumber = source.si_signo;
00076             dest.errorNumber = source.si_errno;
00077             dest.signalCode = source.si_code;
00078 
00079             switch(source.si_code)
00080             {
00081             case SI_USER:
00082                dest.originatingPID = source.si_pid;
00083                dest.originatingUID = source.si_uid;
00084                break;
00085             case SI_TIMER:
00086                dest.timerValue = source.si_value;
00087                break;
00088             case SI_ASYNCIO:
00089 #if defined(OW_HAVE_SIGINFO_T_SI_FD)
00090                dest.fileDescriptor = source.si_fd;
00091 #endif
00092                dest.band = source.si_band;
00093                break;
00094             default:
00095                // UNKNOWN!
00096                break;
00097             }
00098             switch(source.si_signo)
00099             {
00100             case SIGILL:
00101             case SIGFPE:
00102             case SIGTRAP:
00103             case SIGBUS:
00104             case SIGSEGV:
00105                dest.faultAddress = source.si_addr;
00106                break;
00107 #if defined(SIGPOLL)
00108             case SIGPOLL:
00109 #if defined(OW_HAVE_SIGINFO_T_SI_FD)
00110                dest.fileDescriptor = source.si_fd;
00111 #endif
00112                dest.band = source.si_band;
00113                break;
00114 #endif /* defined(SIGPOLL) */
00115             default:
00116                // UNKNOWN.
00117                break;
00118             }
00119 #endif
00120          }
00121 
00122          namespace
00123          {
00124             // A helper function to flatten types to a pipe without performing
00125             // any type conversion (raw data).
00126             // THIS IS ONLY VALID FOR POD TYPES.
00127             template<class T>
00128             void flattenToPipe(const T& t, UnnamedPipeRef& destPipe)
00129             {
00130                destPipe->write(&t, sizeof(t));
00131             }
00132 
00133             // A helper function to unflatten types from a pipe without
00134             // performing any type conversion (raw data).
00135             // THIS IS ONLY VALID FOR POD TYPES.
00136             template <class T>
00137             bool unflattenFromPipe(T& dest, UnnamedPipeRef& sourcePipe)
00138             {
00139                return sourcePipe->read(&dest, sizeof(dest));
00140             }
00141          }
00142 
00143          bool flattenSignalInformation(const SignalInformation& source, UnnamedPipeRef& destPipe)
00144          {
00145             if( !destPipe )
00146             {
00147                return false;
00148             }
00149 
00150             flattenToPipe(source.signalAction, destPipe);
00151             flattenToPipe(source.signalNumber, destPipe);
00152             flattenToPipe(source.errorNumber, destPipe);
00153             flattenToPipe(source.signalCode, destPipe);
00154             flattenToPipe(source.originatingPID, destPipe);
00155             flattenToPipe(source.originatingUID, destPipe);
00156             flattenToPipe(source.timerValue, destPipe);
00157             flattenToPipe(source.faultAddress, destPipe);
00158             flattenToPipe(source.fileDescriptor, destPipe);
00159             flattenToPipe(source.band, destPipe);
00160             return true;
00161          }
00162 
00163          bool unflattenSignalInformation(SignalInformation& dest, UnnamedPipeRef& sourcePipe)
00164          {
00165             if( !sourcePipe )
00166             {
00167                return false;
00168             }
00169             bool success = true;
00170             dest = SignalInformation();
00171 
00172             success = success && unflattenFromPipe(dest.signalAction, sourcePipe);
00173             success = success && unflattenFromPipe(dest.signalNumber, sourcePipe);
00174             success = success && unflattenFromPipe(dest.errorNumber, sourcePipe);
00175             success = success && unflattenFromPipe(dest.signalCode, sourcePipe);
00176             success = success && unflattenFromPipe(dest.originatingPID, sourcePipe);
00177             success = success && unflattenFromPipe(dest.originatingUID, sourcePipe);
00178             success = success && unflattenFromPipe(dest.timerValue, sourcePipe);
00179             success = success && unflattenFromPipe(dest.faultAddress, sourcePipe);
00180             success = success && unflattenFromPipe(dest.fileDescriptor, sourcePipe);
00181             success = success && unflattenFromPipe(dest.band, sourcePipe);
00182 
00183             return success;
00184          }
00185 
00186          std::ostream& operator<<(std::ostream& o, const SignalInformation& sig)
00187          {
00188             const char* sigtext = NULL;
00189 #if defined(OW_HAVE_STRSIGNAL)
00190             sigtext = strsignal(sig.signalNumber);
00191 #endif
00192 
00193             if( !sigtext )
00194             {
00195                sigtext = "UNKNOWN";
00196             }
00197             o << "  Signal: " << sigtext << " (" << sig.signalNumber << ")" << std::endl;
00198             if( sig.errorNumber )
00199             {
00200                o << "  Error: " << strerror(sig.errorNumber) << std::endl;
00201             }
00202 
00203             const char* signal_type = "Unknown-origin signal";
00204 
00205             enum signal_specifications
00206                {
00207                   SIGNAL_ANY,
00208                   SIGNAL_SPECIFIC
00209                };
00210             // A struct to avoid having a huge case statement (using a loop instead)
00211             struct signal_code_text
00212             {
00213                signal_specifications signal_spec;
00214                int signal_number;
00215                int signal_code;
00216                const char* signal_type_text;
00217             };
00218 
00219 #ifndef OW_WIN32
00220             // TODO: The signal code conversion into something that is
00221             // human readable.  This is partially done below.
00222             // Check the signal code table at
00223             // http://www.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html
00224             const signal_code_text signal_text[] =
00225                {
00226 #if defined(SI_USER)
00227                   { SIGNAL_ANY, 0, SI_USER, "User-originated (kill, sigsend, or raise) signal" },
00228 #endif
00229 #if defined(SI_KERNEL)
00230                   { SIGNAL_ANY, 0, SI_KERNEL, "Kernel-originated signal" },
00231 #endif
00232 #if defined(SI_QUEUE)
00233                   { SIGNAL_ANY, 0, SI_QUEUE, "sigqueue queued signal" },
00234 #endif
00235 #if defined(SI_TIMER)
00236                   { SIGNAL_ANY, 0, SI_TIMER, "Timer expiration signal"},
00237 #endif
00238 #if defined(SI_ASYNCIO)
00239                   { SIGNAL_ANY, 0, SI_ASYNCIO, "Asynchronous I/O signal"},
00240 #endif
00241 #if defined(SI_MESGQ)
00242                   { SIGNAL_ANY, 0, SI_MESGQ, "Empty message queue signal"},
00243 #endif
00244 #if defined(SIGILL) && defined(ILL_ILLOPC)
00245                   { SIGNAL_SPECIFIC, SIGILL, ILL_ILLOPC, "Illegal instruction: Illegal opcode"},
00246 #endif
00247 #if defined(SIGILL) && defined(ILL_ILLOPN)
00248                   { SIGNAL_SPECIFIC, SIGILL, ILL_ILLOPN, "Illegal instruction: Illegal operand"},
00249 #endif
00250 #if defined(SIGILL) && defined(ILL_ILLADR)
00251                   { SIGNAL_SPECIFIC, SIGILL, ILL_ILLADR, "Illegal instruction: Illegal addressing mode"},
00252 #endif
00253 #if defined(SIGILL) && defined(ILL_ILLTRP)
00254                   { SIGNAL_SPECIFIC, SIGILL, ILL_ILLTRP, "Illegal instruction: Illegal trap"},
00255 #endif
00256 #if defined(SIGILL) && defined(ILL_PRVOPC)
00257                   { SIGNAL_SPECIFIC, SIGILL, ILL_PRVOPC, "Illegal instruction: Privileged opcode"},
00258 #endif
00259 #if defined(SIGILL) && defined(ILL_PRVREG)
00260                   { SIGNAL_SPECIFIC, SIGILL, ILL_PRVREG, "Illegal instruction: Privileged register"},
00261 #endif
00262 #if defined(SIGILL) && defined(ILL_COPROC)
00263                   { SIGNAL_SPECIFIC, SIGILL, ILL_COPROC, "Illegal instruction: Coprocessor error"},
00264 #endif
00265 #if defined(SIGILL) && defined(ILL_BADSTK)
00266                   { SIGNAL_SPECIFIC, SIGILL, ILL_BADSTK, "Illegal instruction: Internal stack error"},
00267 #endif
00268                };
00269 
00270             for( const signal_code_text* test_signal = signal_text;
00271                  test_signal != (signal_text + sizeof(signal_text) / sizeof(*signal_text));
00272                  ++test_signal )
00273             {
00274                if( test_signal->signal_spec == SIGNAL_ANY )
00275                {
00276                   if( sig.signalCode == test_signal->signal_code )
00277                   {
00278                      signal_type = test_signal->signal_type_text;
00279                      break;
00280                   }
00281                }
00282                else
00283                {
00284                   if(
00285                      (sig.signalNumber == test_signal->signal_number) &&
00286                      (sig.signalCode == test_signal->signal_code) )
00287                   {
00288                      signal_type = test_signal->signal_type_text;
00289                      break;
00290                   }
00291                }
00292             }
00293 #else
00294             signal_type = "UNKNOWN";
00295 #endif
00296 
00297             o << "  Signal Type: " << signal_type << " (" << sig.signalCode << ")" << std::endl;
00298 
00299             // Some of these fields will be meaningless for some types
00300             // (add specific types in their own case).
00301             o << "  Fault address: " << sig.faultAddress << std::endl;
00302             o << "  File Descriptor: " << sig.fileDescriptor << std::endl;
00303             o << "  Band: " << sig.band << std::endl;
00304             o << "  Origination PID: " << sig.originatingPID << std::endl;
00305             o << "  Originating UID: " << sig.originatingUID;
00306             bool success = false;
00307             String username = UserUtils::getUserName(sig.originatingUID, success);
00308             if( success )
00309             {
00310                o << " (" << username << ")";
00311             }
00312             o << std::endl;
00313 
00314             const char* action;
00315             switch( sig.signalAction )
00316             {
00317             case ::OW_NAMESPACE::Platform::SHUTDOWN:
00318                action = "shutdown";
00319                break;
00320             case ::OW_NAMESPACE::Platform::REINIT:
00321                action = "restart";
00322                break;
00323             default:
00324                action = "unknown";
00325                break;
00326             }
00327             o << "  CIMOM Action: " << action << std::endl;
00328             return o;
00329          }
00330 
00331       } // end namespace Signal
00332    } // end namespace Platform
00333 } // end namespace OW_NAMESPACE

Generated on Thu Feb 9 08:48:08 2006 for openwbem by  doxygen 1.4.6