4 * Operating System Process (running program executable) class.
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
30 * Revision 1.66 2004/05/21 00:28:39 csoutheren
31 * Moved PProcessStartup creation to PProcess::Initialise
32 * Added PreShutdown function and called it from ~PProcess to handle PProcessStartup removal
34 * Revision 1.65 2004/05/19 22:27:19 csoutheren
35 * Added fix for gcc 2.95
37 * Revision 1.64 2004/05/18 21:49:25 csoutheren
38 * Added ability to display trace output from program startup via environment
39 * variable or by application creating a PProcessStartup descendant
41 * Revision 1.63 2004/05/18 06:01:06 csoutheren
42 * Deferred plugin loading until after main has executed by using abstract factory classes
44 * Revision 1.62 2004/05/13 14:54:57 csoutheren
45 * Implement PProcess startup and shutdown handling using abstract factory classes
47 * Revision 1.61 2003/11/25 08:28:13 rjongbloed
48 * Removed ability to have platform without threads, win16 finally deprecated
50 * Revision 1.60 2003/09/17 05:41:59 csoutheren
51 * Removed recursive includes
53 * Revision 1.59 2003/09/17 01:18:02 csoutheren
54 * Removed recursive include file system and removed all references
55 * to deprecated coooperative threading support
57 * Revision 1.58 2002/12/11 22:23:59 robertj
58 * Added ability to set user identity temporarily and permanently.
59 * Added get and set users group functions.
61 * Revision 1.57 2002/12/02 03:57:18 robertj
62 * More RTEMS support patches, thank you Vladimir Nesic.
64 * Revision 1.56 2002/10/17 13:44:27 robertj
65 * Port to RTEMS, thanks Vladimir Nesic.
67 * Revision 1.55 2002/10/17 07:17:42 robertj
68 * Added ability to increase maximum file handles on a process.
70 * Revision 1.54 2002/10/10 04:43:43 robertj
71 * VxWorks port, thanks Martijn Roest
73 * Revision 1.53 2002/09/16 01:08:59 robertj
74 * Added #define so can select if #pragma interface/implementation is used on
75 * platform basis (eg MacOS) rather than compiler, thanks Robert Monaghan.
77 * Revision 1.52 2002/07/30 02:55:48 craigs
78 * Added program start time to PProcess
79 * Added virtual to GetVersion etc
81 * Revision 1.51 2002/02/14 05:13:33 robertj
82 * Fixed possible deadlock if a timer is deleted (however indirectly) in the
83 * OnTimeout of another timer.
85 * Revision 1.50 2001/11/23 06:59:29 robertj
86 * Added PProcess::SetUserName() function for effective user changes.
88 * Revision 1.49 2001/08/11 07:57:30 rogerh
89 * Add Mac OS Carbon changes from John Woods <jfw@jfwhome.funhouse.com>
91 * Revision 1.48 2001/05/22 12:49:32 robertj
92 * Did some seriously wierd rewrite of platform headers to eliminate the
93 * stupid GNU compiler warning about braces not matching.
95 * Revision 1.47 2001/03/09 05:50:48 robertj
96 * Added ability to set default PConfig file or path to find it.
98 * Revision 1.46 2001/01/02 07:47:44 robertj
99 * Fixed very narrow race condition in timers (destroyed while in OnTimeout()).
101 * Revision 1.45 2000/08/30 03:16:59 robertj
102 * Improved multithreaded reliability of the timers under stress.
104 * Revision 1.44 2000/04/03 18:42:40 robertj
105 * Added function to determine if PProcess instance is initialised.
107 * Revision 1.43 2000/02/29 12:26:14 robertj
108 * Added named threads to tracing, thanks to Dave Harvey
110 * Revision 1.42 1999/03/09 02:59:50 robertj
111 * Changed comments to doc++ compatible documentation.
113 * Revision 1.41 1999/02/16 08:11:09 robertj
114 * MSVC 6.0 compatibility changes.
116 * Revision 1.40 1999/01/30 14:28:10 robertj
117 * Added GetOSConfigDir() function.
119 * Revision 1.39 1999/01/11 11:27:11 robertj
120 * Added function to get the hardware process is running on.
122 * Revision 1.38 1998/11/30 02:51:00 robertj
123 * New directory structure
125 * Revision 1.37 1998/10/18 14:28:44 robertj
126 * Renamed argv/argc to eliminate accidental usage.
128 * Revision 1.36 1998/10/13 14:06:13 robertj
129 * Complete rewrite of memory leak detection code.
131 * Revision 1.35 1998/09/23 06:21:10 robertj
132 * Added open source copyright license.
134 * Revision 1.34 1998/09/14 12:30:38 robertj
135 * Fixed memory leak dump under windows to not include static globals.
137 * Revision 1.33 1998/04/07 13:33:53 robertj
138 * Changed startup code to support PApplication class.
140 * Revision 1.32 1998/04/01 01:56:21 robertj
141 * Fixed standard console mode app main() function generation.
143 * Revision 1.31 1998/03/29 06:16:44 robertj
144 * Rearranged initialisation sequence so PProcess descendent constructors can do "things".
146 * Revision 1.30 1998/03/20 03:16:10 robertj
147 * Added special classes for specific sepahores, PMutex and PSyncPoint.
149 * Revision 1.29 1997/07/08 13:13:46 robertj
152 * Revision 1.28 1997/04/27 05:50:13 robertj
155 * Revision 1.27 1997/02/05 11:51:56 robertj
156 * Changed current process function to return reference and validate objects descendancy.
158 * Revision 1.26 1996/06/28 13:17:08 robertj
159 * Fixed incorrect declaration of internal timer list.
161 * Revision 1.25 1996/06/13 13:30:49 robertj
162 * Rewrite of auto-delete threads, fixes Windows95 total crash.
164 * Revision 1.24 1996/05/23 09:58:47 robertj
165 * Changed process.h to pprocess.h to avoid name conflict.
166 * Added mutex to timer list.
168 * Revision 1.23 1996/05/18 09:18:30 robertj
169 * Added mutex to timer list.
171 * Revision 1.22 1996/04/29 12:18:48 robertj
172 * Added function to return process ID.
174 * Revision 1.21 1996/03/12 11:30:21 robertj
175 * Moved destructor to platform dependent code.
177 * Revision 1.20 1996/02/25 11:15:26 robertj
178 * Added platform dependent Construct function to PProcess.
180 * Revision 1.19 1996/02/03 11:54:09 robertj
181 * Added operating system identification functions.
183 * Revision 1.18 1996/01/02 11:57:17 robertj
184 * Added thread for timers.
186 * Revision 1.17 1995/12/23 03:46:02 robertj
187 * Changed version numbers.
189 * Revision 1.16 1995/12/10 11:33:36 robertj
190 * Added extra user information to processes and applications.
191 * Changes to main() startup mechanism to support Mac.
193 * Revision 1.15 1995/06/17 11:13:05 robertj
194 * Documentation update.
196 * Revision 1.14 1995/06/17 00:43:10 robertj
197 * Made PreInitialise virtual for NT service support
199 * Revision 1.13 1995/03/14 12:42:14 robertj
200 * Updated documentation to use HTML codes.
202 * Revision 1.12 1995/03/12 04:43:26 robertj
203 * Remvoed redundent destructor.
205 * Revision 1.11 1995/01/11 09:45:09 robertj
206 * Documentation and normalisation.
208 * Revision 1.10 1994/08/23 11:32:52 robertj
211 * Revision 1.9 1994/08/22 00:46:48 robertj
212 * Added pragma fro GNU C++ compiler.
214 * Revision 1.8 1994/08/21 23:43:02 robertj
215 * Added function to get the user name of the owner of a process.
217 * Revision 1.7 1994/08/04 11:51:04 robertj
218 * Moved OperatingSystemYield() to protected for Unix.
220 * Revision 1.6 1994/08/01 03:42:23 robertj
221 * Destructor needed for heap debugging.
223 * Revision 1.5 1994/07/27 05:58:07 robertj
226 * Revision 1.4 1994/07/21 12:33:49 robertj
227 * Moved cooperative threads to common.
229 * Revision 1.3 1994/06/25 11:55:15 robertj
230 * Unix version synchronisation.
241 #include <ptlib/mutex.h>
242 #include <ptlib/syncpoint.h>
243 #include <ptlib/pfactory.h>
247 This macro is used to create the components necessary for a user PWLib
248 process. For a PWLib program to work correctly on all platforms the
249 #main()# function must be defined in the same module as the
250 instance of the application.
252 #ifndef P_MAC_MPTHREADS
254 #define PCREATE_PROCESS(cls) \
255 PProcess::PreInitialise(0, NULL, NULL); \
258 #elif defined(P_RTEMS)
259 #define PCREATE_PROCESS(cls) \
261 void* POSIX_Init( void* argument) \
262 { PProcess::PreInitialise(0, 0, 0); \
263 static cls instance; \
264 exit( instance._main() ); \
268 #define PCREATE_PROCESS(cls) \
269 int main(int argc, char ** argv, char ** envp) \
270 { PProcess::PreInitialise(argc, argv, envp); \
271 static cls instance; \
272 return instance._main(); \
275 #else // Mac MP Tasks implementation
276 // Alas, a Macintosh main thread has a number of important responsibilities.
277 // The goal of this code is to warm up the Toolbox and create an independant
278 // thread for the application object. I'm trying to wrap a generic Mac main
279 // function around an existing derived PProcess class; a real Mac application
280 // may want to duplicate this code in a more suitable form after rewriting the
281 // canonical Main() implementation.
282 // I have changed the process instance variable to be automatic rather than
283 // static duration so I can tear down the Mac MP framework.
284 // In practice, I think it is better to hand-craft the main function, but this
285 // allows the asn compiler to build and run.
286 // The declarations are available in <ptlib/MacMainIf.h>.
287 #define PCREATE_PROCESS(cls) \
289 extern int MacInitialisePWLibEvents(void); \
290 typedef long(*callback_api_c)(void*); \
291 extern int SpawnProcessInContext(callback_api_c); \
292 extern void RunApplicationEventLoop(void); \
293 static long PWTrampoline(void *ignored) \
296 return instance._main(); \
299 int main(int argc, char ** argv, char ** envp) \
302 MacInitialisePWLibEvents(); \
303 PProcess::PreInitialise(argc, argv, envp); \
304 err = SpawnProcessInContext(PWTrampoline); \
305 if (err == 0) RunApplicationEventLoop(); \
310 /*$MACRO PDECLARE_PROCESS(cls,ancestor,manuf,name,major,minor,status,build)
311 This macro is used to declare the components necessary for a user PWLib
312 process. This will declare the PProcess descendent class, eg PApplication,
313 and create an instance of the class. See the #PCREATE_PROCESS# macro
316 #define PDECLARE_PROCESS(cls,ancestor,manuf,name,major,minor,status,build) \
317 class cls : public ancestor { \
318 PCLASSINFO(cls, ancestor); \
320 cls() : ancestor(manuf, name, major, minor, status, build) { } \
322 virtual void Main(); \
326 PLIST(PInternalTimerList
, PTimer
);
328 class PTimerList
: PInternalTimerList
// Want this to be private
329 /* This class defines a list of #PTimer# objects. It is primarily used
330 internally by the library and the user should never create an instance of
331 it. The #PProcess# instance for the application maintains an instance
332 of all of the timers created so that it may decrements them at regular
336 PCLASSINFO(PTimerList
, PInternalTimerList
);
340 // Create a new timer list
342 PTimeInterval
Process();
343 /* Decrement all the created timers and dispatch to their callback
344 functions if they have expired. The #PTimer::Tick()# function
345 value is used to determine the time elapsed since the last call to
348 The return value is the number of milliseconds until the next timer
349 needs to be despatched. The function need not be called again for this
350 amount of time, though it can (and usually is).
353 maximum time interval before function should be called again.
357 PMutex listMutex
, processingMutex
, inTimeoutMutex
;
358 // Mutual exclusion for multi tasking
360 PTimeInterval lastSample
;
361 // The last system timer tick value that was used to process timers.
363 PTimer
* currentTimer
;
364 // The timer which is currently being handled
370 ///////////////////////////////////////////////////////////////////////////////
373 /**This class represents an operating system process. This is a running
374 "programme" in the context of the operating system. Note that there can
375 only be one instance of a PProcess class in a given programme.
377 The instance of a PProcess or its GUI descendent #PApplication# is
378 usually a static variable created by the application writer. This is the
379 initial "anchor" point for all data structures in an application. As the
380 application writer never needs to access the standard system
381 #main()# function, it is in the library, the programmes
382 execution begins with the virtual function #PThread::Main()# on a
385 class PProcess
: public PThread
387 PCLASSINFO(PProcess
, PThread
);
390 /**@name Construction */
392 /// Release status for the program.
394 /// Code is still very much under construction.
396 /// Code is largely complete and is under test.
398 /// Code has all known bugs removed and is shipping.
403 /** Create a new process instance.
406 const char * manuf
= "", /// Name of manufacturer
407 const char * name
= "", /// Name of product
408 WORD majorVersion
= 1, /// Major version number of the product
409 WORD minorVersion
= 0, /// Minor version number of the product
410 CodeStatus status
= ReleaseCode
, /// Development status of the product
411 WORD buildNumber
= 1 /// Build number of the product
415 /**@name Overrides from class PObject */
417 /**Compare two process instances. This should almost never be called as
418 a programme only has access to a single process, its own.
421 #EqualTo# if the two process object have the same name.
424 const PObject
& obj
/// Other process to compare against.
428 /**@name Overrides from class PThread */
430 /**Terminate the process. Usually only used in abnormal abort situation.
432 virtual void Terminate();
434 /** Get the name of the thread. Thread names are a optional debugging aid.
439 virtual PString
GetThreadName() const;
441 /** Change the name of the thread. Thread names are a optional debugging aid.
446 virtual void SetThreadName(
447 const PString
& name
/// New name for the thread.
451 /**@name Process information functions */
453 /**Get the current processes object instance. The {\it current process}
454 is the one the application is running in.
457 pointer to current process instance.
459 static PProcess
& Current();
461 /**Determine if the current processes object instance has been initialised.
462 If this returns TRUE it is safe to use the PProcess::Current() function.
465 TRUE if process class has been initialised.
467 static BOOL
IsInitialised();
469 /**Set the termination value for the process.
471 The termination value is an operating system dependent integer which
472 indicates the processes termiantion value. It can be considered a
473 "return value" for an entire programme.
475 void SetTerminationValue(
476 int value
/// Value to return a process termination status.
479 /**Get the termination value for the process.
481 The termination value is an operating system dependent integer which
482 indicates the processes termiantion value. It can be considered a
483 "return value" for an entire programme.
486 integer termination value.
488 int GetTerminationValue() const;
490 /**Get the programme arguments. Programme arguments are a set of strings
491 provided to the programme in a platform dependent manner.
494 argument handling class instance.
496 PArgList
& GetArguments();
498 /**Get the name of the manufacturer of the software. This is used in the
499 default "About" dialog box and for determining the location of the
500 configuration information as used by the #PConfig# class.
502 The default for this information is the empty string.
505 string for the manufacturer name eg "Equivalence".
507 virtual const PString
& GetManufacturer() const;
509 /**Get the name of the process. This is used in the
510 default "About" dialog box and for determining the location of the
511 configuration information as used by the #PConfig# class.
513 The default is the title part of the executable image file.
516 string for the process name eg "MyApp".
518 virtual const PString
& GetName() const;
520 /**Get the version of the software. This is used in the default "About"
521 dialog box and for determining the location of the configuration
522 information as used by the #PConfig# class.
524 If the #full# parameter is TRUE then a version string
525 built from the major, minor, status and build veriosn codes is
526 returned. If FALSE then only the major and minor versions are
529 The default for this information is "1.0".
532 string for the version eg "1.0b3".
534 virtual PString
GetVersion(
535 BOOL full
= TRUE
/// TRUE for full version, FALSE for short version.
538 /**Get the processes executable image file path.
541 file path for program.
543 const PFilePath
& GetFile() const;
545 /**Get the platform dependent process identifier for the process. This is
546 an arbitrary (and unique) integer attached to a process by the operating
550 Process ID for process.
552 DWORD
GetProcessID() const;
554 /**Get the effective user name of the owner of the process, eg "root" etc.
555 This is a platform dependent string only provided by platforms that are
556 multi-user. Note that some value may be returned as a "simulated" user.
557 For example, in MS-DOS an environment variable
560 user name of processes owner.
562 PString
GetUserName() const;
564 /**Set the effective owner of the process.
565 This is a platform dependent string only provided by platforms that are
568 For unix systems if the username may consist exclusively of digits and
569 there is no actual username consisting of that string then the numeric
570 uid value is used. For example "0" is the superuser. For the rare
571 occassions where the users name is the same as their uid, if the
572 username field starts with a '#' then the numeric form is forced.
574 If an empty string is provided then original user that executed the
575 process in the first place (the real user) is set as the effective user.
577 The permanent flag indicates that the user will not be able to simple
578 change back to the original user as indicated above, ie for unix
579 systems setuid() is used instead of seteuid(). This is not necessarily
580 meaningful for all platforms.
583 TRUE if processes owner changed. The most common reason for failure is
584 that the process does not have the privilege to change the effective user.
587 const PString
& username
, /// New user name or uid
588 BOOL permanent
= FALSE
/// Flag for if effective or real user
591 /**Get the effective group name of the owner of the process, eg "root" etc.
592 This is a platform dependent string only provided by platforms that are
593 multi-user. Note that some value may be returned as a "simulated" user.
594 For example, in MS-DOS an environment variable
597 group name of processes owner.
599 PString
GetGroupName() const;
601 /**Set the effective group of the process.
602 This is a platform dependent string only provided by platforms that are
605 For unix systems if the groupname may consist exclusively of digits and
606 there is no actual groupname consisting of that string then the numeric
607 uid value is used. For example "0" is the superuser. For the rare
608 occassions where the groups name is the same as their uid, if the
609 groupname field starts with a '#' then the numeric form is forced.
611 If an empty string is provided then original group that executed the
612 process in the first place (the real group) is set as the effective
615 The permanent flag indicates that the group will not be able to simply
616 change back to the original group as indicated above, ie for unix
617 systems setgid() is used instead of setegid(). This is not necessarily
618 meaningful for all platforms.
621 TRUE if processes group changed. The most common reason for failure is
622 that the process does not have the privilege to change the effective
626 const PString
& groupname
, /// New group name or gid
627 BOOL permanent
= FALSE
/// Flag for if effective or real group
630 /**Get the maximum file handle value for the process.
631 For some platforms this is meaningless.
634 user name of processes owner.
636 int GetMaxHandles() const;
638 /**Set the maximum number of file handles for the process.
639 For unix systems the user must be run with the approriate privileges
640 before this function can set the value above the system limit.
642 For some platforms this is meaningless.
645 TRUE if successfully set the maximum file hadles.
648 int newLimit
/// New limit on file handles
651 /**Get the default file to use in PConfig instances.
653 virtual PString
GetConfigurationFile();
655 /**Set the default file or set of directories to search for use in PConfig.
656 To find the .ini file for use in the default PConfig() instance, this
657 explicit filename is used, or if it is a set of directories separated
658 by either ':' or ';' characters, then the application base name postfixed
659 with ".ini" is searched for through those directories.
661 The search is actually done when the GetConfigurationFile() is called,
662 this function only sets the internal variable.
664 Note for Windows, a path beginning with "HKEY_LOCAL_MACHINE\\" or
665 "HKEY_CURRENT_USER\\" will actually search teh system registry for the
666 application base name only (no ".ini") in that folder of the registry.
668 void SetConfigurationPath(
669 const PString
& path
/// Explicit file or set of directories
673 /**@name Operating System information functions */
675 /**Get the class of the operating system the process is running on, eg
681 static PString
GetOSClass();
683 /**Get the name of the operating system the process is running on, eg
689 static PString
GetOSName();
691 /**Get the hardware the process is running on, eg "sparc".
696 static PString
GetOSHardware();
698 /**Get the version of the operating system the process is running on, eg
702 String for OS version.
704 static PString
GetOSVersion();
706 /**Get the configuration directory of the operating system the process is
707 running on, eg "/etc" for Unix, "c:\windows" for Win95 or
708 "c:\winnt\system32\drivers\etc" for NT.
711 Directory for OS configuration files.
713 static PDirectory
GetOSConfigDir();
716 PTimerList
* GetTimerList();
717 /* Get the list of timers handled by the application. This is an internal
718 function and should not need to be called by the user.
724 static void PreInitialise(
725 int argc
, // Number of program arguments.
726 char ** argv
, // Array of strings for program arguments.
727 char ** envp
// Array of string for the system environment
729 /* Internal initialisation function called directly from
730 #_main()#. The user should never call this function.
733 static void PreShutdown();
734 /* Internal shutdown function called directly from the ~PProcess
735 #_main()#. The user should never call this function.
738 virtual int _main(void * arg
= NULL
);
739 // Main function for process, called from real main after initialisation
741 PTime
GetStartTime() const;
742 /* return the time at which the program was started
750 static char ** p_argv
;
751 static char ** p_envp
;
754 int terminationValue
;
755 // Application return value
757 PString manufacturer
;
758 // Application manufacturer name.
761 // Application executable base name from argv[0]
764 // Major version number of the product
767 // Minor version number of the product
770 // Development status of the product
773 // Build number of the product
775 PFilePath executableFile
;
776 // Application executable file from argv[0] (not open)
778 PStringList configurationPaths
;
779 // Explicit file or set of directories to find default PConfig
782 // The list of arguments
785 // List of active timers in system
787 PTime programStartTime
;
788 // time at which process was intantiated, i.e. started
791 // Maximum number of file handles process can open.
794 friend class PThread
;
797 // Include platform dependent part of class
799 #include "msos/ptlib/pprocess.h"
801 #include "unix/ptlib/pprocess.h"
806 * one instance of this class (or any descendants) will be instantiated
807 * via PGenericFactory<PProessStartup> one "main" has been started, and then
808 * the OnStartup() function will be called. The OnShutdown function will
809 * be called after main exits, and the instances will be destroyed if they
812 class PProcessStartup
: public PObject
814 PCLASSINFO(PProcessStartup
, PObject
)
816 virtual void OnStartup() { }
817 virtual void OnShutdown() { }
820 typedef PGenericFactory
<PProcessStartup
> PProcessStartupFactory
;
822 // using an inline definition rather than a #define crashes gcc 2.95. Go figure
823 #define P_DEFAULT_TRACE_OPTIONS ( PTrace::Blocks | PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine )
825 template <unsigned _level
, unsigned _options
= P_DEFAULT_TRACE_OPTIONS
>
826 class PTraceLevelSetStartup
: public PProcessStartup
830 { PTrace::Initialise(_level
, NULL
, _options
); }
835 // End Of File ///////////////////////////////////////////////////////////////