/* * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ // // unixchild - low-level UNIX process child management // #ifndef _H_UNIXCHILD #define _H_UNIXCHILD #include <security_utilities/utilities.h> #include <security_utilities/errors.h> #include <security_utilities/globalizer.h> #include <sys/types.h> #include <sys/wait.h> #include <map> #include <list> namespace Security { namespace UnixPlusPlus { // // A Child object represents a (potential) fork-child of your process. // It could be a clean fork or a fork/exec; this layer doesn't care. // It is meant to track the UNIX-life of that process. // Subclass Child or use it as a mix-in. // // Child keeps track of all alive children; Child::find<>() can locate them // by pid if you like. Other children are not collected; you've got to do this // yourself. // class Child { public: Child(); virtual ~Child(); enum State { unborn, // never forked alive, // last seen alive dead, // coroner confirms death stopped, // stopped due to trace or job control (not implemented) abandoned, // cut loose (via forget()) invalid // system says we're all confused about this child }; void fork(); // do the forky-forky State state() const { return mState; } operator bool () const { return mState == alive; } pid_t pid() const { assert(mState != unborn); return mPid; } State check(); // update status on (just) this child and return new state void wait(); // wait for (just) this Child to die void kill(int signal); // send signal to child (if alive) void kill(); // bring me its head, NOW // status is only available for dead children int waitStatus() const; // raw wait(2) status byte bool succeeded() const { return waitStatus() == 0; } bool bySignal() const; // was killed by a signal int exitCode() const; // exit() code; valid only if !bySignal() int exitSignal() const; // signal that killed child; valid only if bySignal() bool coreDumped() const; // child dumped core when it died protected: virtual void childAction() = 0; // called in child after fork() virtual void parentAction(); // called in parent after fork() virtual void dying(); // called when child is confirmed dead void abandon(); // cut a living child loose (forget about it) private: State mState; // child state pid_t mPid; // pid of child (if born) int mStatus; // exit status (if dead) bool checkStatus(int options); // check status of this Child (wait4) void bury(int status); // canonical last rites static Child *findGeneric(pid_t pid); // find living child by pid void tryKill(int signal); class Bier: public std::list<Child *> { public: void add(Child *child) { this->push_back(child); } void notify(); }; public: // set sharedChildren(true) in library code to leave other children alone static void sharedChildren(bool s); static bool sharedChildren(); void reset(); // make Child ready to be born again (forgets all state) static void checkChildren(); // update status on living offspring template <class Subclass> static Subclass *find(pid_t pid) { return dynamic_cast<Subclass *>(findGeneric(pid)); } private: struct Children : public Mutex, public std::map<pid_t, Child *> { Children() : shared(false) { } bool shared; }; static ModuleNexus<Children> mChildren; }; } // end namespace UnixPlusPlus } // end namespace Security #endif //_H_UNIXCHILD