Last revised: 09Apr2002 GLGTable of Contents
The demo program for the Easy Posix Toolkit for Java is not a conventional demo that showcases available features. Instead, it wraps around another program of your choice, and uses some of the Easy Posix Toolkit features to help the other program run better. "Better" means that it handles signals more safely, adjusts resource-limits, and does other things before the other program takes control. Some of these things can be done from command shells, but since I'm demo'ing the Easy Posix Toolkit I'll do them there instead.The principal class in the demo is app.posix.pita.Pita. It's the wrapper class for the underlying service, and also defines a main() entry-point. By "underlying service" I simply mean another program with a main() entry-point. It may be a server-like service, or it may be a GUI-interactive program. The things that Pita can do are often of more benefit to server-like Java programs, but you can use Pita anywhere you want.
The Pita wrapper is configurable. You tell it which class to run as the underlying service, along with other things that you want done before the service is run. The wrapper is configured entirely through system properties. In command-line environments, you would define these with "-Dname=-value" options. In the Mac OS X environment, you can use a command-line, or you can use an "Info.plist" file, or a properties-file. However you define the system properties, the Pita wrapper reads them, does what they tell it, then invokes the underlying service's main(String[]) method with all the command-line args it receives.
All the Pita configuration properties match a naming pattern. There is only one property whose name is fixed, and that's the property that defines the naming pattern. The naming pattern is simply a prefix, which all configuration properties must have in order to be recognized. If you define a different prefix, then Pita will look only for properties whose name starts with that prefix. The only property with a completely fixed name is "app.posix.pita.name.prefix", whose value is the prefix for all other names. The default for "app.posix.pita.name.prefix" is "app.posix.pita." (note the trailing dot), so the default configurable property-names are all in the pattern "app.posix.pita.*".
All the other configuring properties must match the prefix you define, so the following discussion uses the term "unprefixed property-name" when discussing the individual properties. The actual property-name used would then consist of the defined prefix (either the default or the one you defined) followed by the unprefixed name. For example, if you don't define a new value for "app.posix.pita.name.prefix", the prefix is "app.posix.pita." (note the trailing dot). So when I say "The unprefixed property name is 'service'", you know that the actual property name needed is "app.posix.pita.service". As another example, let's say you define the property:
app.posix.pita.name.prefix = trial.That means all the other configuring properties will start with "trial.", like so:trial.service = app.posix.pita.Wastrel trial.limit.CPU = 15 trial.signals.EXITING = SIGXCPUThe unprefixed names of the configuring properties are:
- service -- the fully qualified class name of the class whose main() method is run as the underlying service. The given class must be public and it must have a method that looks like this:
public static void main( String[] )
If the class can't be loaded, or it's not public, or it isn't static, or it doesn't take a String[], or it doesn't return void, then the Pita.main() method will die with an IllegalArgumentException.
(default: none; you must specify a valid service class)
As an aid to experimentation, a simple time-wasting service class is provided in app.posix.pita.Wastrel. Define it as the service class and you can play around with the other Pita configuration properties.
- posix.factory -- the fully qualified class name of a specific Posix imp to be used instead of the default imp that would otherwise be selected for the platform.
(default: empty, so default Posix imp for platform is selected)
- umask -- a decimal (nn), or octal (0nn), or hex (0xnn or #nn) number specifying the umask to set. See 'man umask' for what the umask does.
(default: empty, so the umask is simply inherited from the parent process)
- nice -- a signed decimal number specifying the nice-level to set. Negative numbers produce more favorable scheduling. Only the superuser (or a setuid-root program) can use negative nice levels. The shell commands 'nice' and 'renice' do similar things.
(default: empty, so the nice-level is simply inherited from the parent process)
- limit.* -- the properties in this naming pattern specify resource-limits. All the values are decimal numbers that designate a soft-limit value. The "*" is replaced by any name String that Environs.getLimit() will accept. For example, you would specify the Descriptors limit with the name limit.Descriptors and the File-size limit with the name limit.File-size. The limit-name must be supported by the Posix imp selected for the platform. If it's not, or if the soft-limit would exceed an established hard-limit, then an error message appears on standard-error. If the soft-limit value is negative, then the resource-limit is unchanged from the inherited value.
(default: none, so resource-limits are all inherited from the parent process)
- signals.XX -- the properties in this naming pattern specify signal disposition. The XX must be one of the disposition names EXITING, IGNORED, NORMAL, or SPEWING. The value of each property is a comma- and/or blank-separated list of signal-names which are to have the particular disposition. Thus, the property-name states the disposition of all the signals named in its value. All the dispositions except SPEWING are as described in the doc-comments for the class glguerin.posix.Signals. Signals designated as SPEWING are caught and elicit a diagnostic output on standard-error. See the class app.posix.pita.Spewer to see all of what's spewed.
(default: none, so all signal dispositions are inherited from the parent process)
Some sample configurations of the Pita service wrapper can be found in the "Demo" directory. They are all text files. They consist of Unix shell command-lines, and have been tested on Mac OS X. On Mac OS X, you can drag-n-drop from TextEdit into a Terminal window and the command-line will be executed.If you run the Wastrel service and establish a SPEWING signal disposition, you can send signals to the Wastrel process and it will spew diagnostics on standard-error. (In the samples, SIGINFO is set to SPEWING, but you can use any signal that's safe and sensible for your program.) Use the command 'ps -aclx' to discover the process ID (PID) that you send the signals to. Use the command 'kill -INFO pid' to send the SIGINFO signal that typically is assigned to spewing. See 'man ps' and 'man kill' for more information.
If you run Wastrel directly, you can interrupt it with SIGINT or SIGTERM and it will terminate. Contrast that with running Wastrel wrapped inside Pita, and with SIGINT and SIGTERM set to the IGNORED disposition.
Beside setting signals to be IGNORED, you can set them to be EXITING. For example, a server-like Java program might behave better with SIGHUP set to EXITING as opposed to if you just left SIGHUP set to NORMAL. You can set other signals to EXITING, too. (I advise leaving the catastrophic-error signals like SIGSEGV and SIGBUS as NORMAL, and setting the core-dump limit high enough that a usable core-dump file is generated.)
Remember that on Mac OS X you can change what a double-clickable Java program's entry-point is simply by editing its "MRJApp.properties" file or its "Info.plist" file appropriately. This makes it very easy to put Pita wrappers around other Java programs, especially if you install "All-Posix.jar" as one of the standard extension JARs. That way it will be available to all programs, and you won't have to change their classpaths in order to use Pita or the Easy Posix Toolkit. See the Release Notes for Mac OS X Java 10.1 for details on the innards of double-clickable app bundles, and the locations for standard extension JARs. How extension JARs are found and loaded depends on the platform, and Mac OS X has simpler and more elegant means than CLASSPATH.
To Greg's Home Page
To Greg's Software Page