From VisualWorks®, 7.6 of March 3, 2008 on March 3, 2008 at 9:47:09 pm (Dialog confirm: 'You are filing-in a Parcel source file!\\While this is possible it will not have\the same effect as loading the parcel.\None of the Parcel''s prerequisites will\be loaded and none of its load actions\will be performed.\\Are you sure you want to file-in?' withCRs) ifFalse: [self error: 'Parcel file-in abandoned. Choose terminate or close.'] <class> <name>HeadlessFont</name> <environment>Graphics</environment> <super>Graphics.ImplementationFont</super> <private>false</private> none <imports></imports> <category>Graphics-Fonts</category> <attributes> <package>Headless</package> </attributes> </class> <comment> Graphics.HeadlessFont
HeadlessFont acts as a stand-in for actual font behavior in lieu of a WindowingSystem in a HeadlessImage.
</comment> <class> <name>AbstractStreamTranscript</name> <environment>OS</environment> <super>Core.Object</super> <private>false</private> none stream transcript <imports></imports> <category>Headless-Support</category> <attributes> <package>Headless</package> </attributes> </class> <comment> OS.AbstractStreamTranscript
AbstractStreamTranscript is an abstract superclass for classes that send Transcript output to some form of stream. Instances are intended to be dependents of Transcript. Transcript (an instance of TextCollector) will send out change notifications (#value, #appendEntry and #update) when it has been changed. By adding an instance of this class as a dependent to Transcript, it can respond to those messages and will store any new output to its stream instance variable. Subclasses of AbstractStreamTranscript are used by the default instance of HeadlessImage to control where output for Transcript is directed. On instance creation, this class will set its transcript instance variable to be Transcript. It then will refer to the instance variable when it receives the appendEntry message in order to ask the Transcript what was just written to the transcript. If a different instance of TextCollector (other than the system global Transcript) is intended to be used, one can set it with #transcript:. Instance Variables: stream <ReadAppendStream> The stream for writing the result of nextEntry transcript <TextCollector> See above
</comment> <class> <name>FileTranscript</name> <environment>OS</environment> <super>OS.AbstractStreamTranscript</super> <private>false</private> none filename <imports></imports> <category>Headless-Support</category> <attributes> <package>Headless</package> </attributes> </class> <comment> OS.FileTranscript
FileTranscript will set its stream instance variable to be associated with a specific filename. To set the filename (and create the stream), use #filename: method. The stream's encoding will be UTF8. Note, the stream is not closed automatically. It will close automatically when the image exits, but if the file is detached without quitting the image, then users of FileTranscript are expected to send #release to an instance of FileTranscript to ensure that the stream is closed Instance Variables: filename <Filename> The filename to use for the stream
</comment> <class> <name>StandardOutTranscript</name> <environment>OS</environment> <super>OS.AbstractStreamTranscript</super> <private>false</private> none current <imports></imports> <category>Headless-Support</category> <attributes> <package>Headless</package> </attributes> </class> <comment> OS.StandardOutTranscript
When an instance of StandardOutTranscript is created, it sets its stream instance variable to be the stream associated with standard out. Therefore, once the instance of this class is added as a dependent to Transcript it will echo Transcript's output to standard out. For convenience, a singleton instance of StandardOutTranscript can be used be sending the class side message #current. Class Instance Variables: current <StandardOutTranscript> A singleton instance of StandardOutTranscript
</comment> <class> <name>HeadlessImage</name> <environment>Core</environment> <super>Core.Subsystem</super> <private>false</private> none isTerminating startupFilename transcriptFilename currentlyHeadless shouldSaveHeadless transcriptToStandardOut transcriptToStandardOutHeadless transcriptToFile transcriptToFileHeadless suspendedProcesses stackDumpStream <imports></imports> <category>Headless-Support</category> <attributes> <package>Headless</package> </attributes> </class> <comment> Core.HeadlessImage
HeadlessImage is a Subsystem that when resumed will decide whether the WindowSystem can be activated. The instance variable, currentlyHeadless, controls the activation of WindowSystem. When currentlyHeadless is false, none of the windows will be displayed and the image will be "headless", so that it can run in a graphic-less environment. Window system interface code checks if it can access a window system and if it can not #cannotSend will be sent to the current instance of HeadlessSystem. In #cannotSend, the current context stack will be dumped to the Transcript. Depending on the value of the isTerminating instance variable the image will either continue running (false) or it will suspend the process and save the image headfull. To debug such a process, the headless image must be saved headfull and restarted. Then the process monitor can be used to debug the offending process. On image start-up, if the image is headless it will optionally reads in a startup file. The file must contain Smalltalk expressions in file-in format. The instance method protocol #'command-line options' contains command line options to pass at image start-up to configure the behavior of the headless image. The Transcript might be handled differently when the image is headless versus headfull. Depending on the return values of the methods, shouldSendTranscriptToStandardOut and shouldSendTranscriptToFile, the output for Transcript might be sent to the stream associated with standard out or a file, or both. This occurs in the #setupTranscript method which will be called with either the BasicHeadfulGraphicsSystem or BasicHeadlessSystem is activated. Instance Variables: isTerminating <Boolean> If true, then whenever an error occurs that attempts to interact with the windowing system (cannotSend is sent to the default instance of HeadlessImage), save the image in a headfull state with the offending process suspended. startupFilename <String | nil> The name of the startup file. When nil, no startup file is filed in. transcriptFilename <String | nil> The name of the transcript file. When nil, no transcript file is used. currentlyHeadless <Boolean> Indicates whether the image is currently running headless. shouldSaveHeadless <Boolean> When we save this image, should it be saved as headless or not transcriptToStandardOut <Boolean> If true, echo Transcript output to standard out when headfull or headless. transcriptToStandardOutHeadless <Boolean> If true, echo Transcript output to standard out only when headless. transcriptToFile <Boolean> If true, echo Transcript output to a file when headfull or headless transcriptToFileHeadless <Boolean> If true, echo Transcript output to a file only when headless suspendedProcesses <Dictionary of: Process> When cannotSend is sent to Headless image, the process that sent the message is saved in this dictionary stackDumpStream <WriteStream> Where do we dump the stack to. If nil, we use the Transcript.
</comment> <class> <name>BasicHeadlessSystem</name> <environment>Core</environment> <super>Graphics.BasicGraphicsSystem</super> <private>false</private> none oldNotifier headlessNotifier <imports></imports> <category>Headless</category> <attributes> <package>Headless</package> </attributes> </class> <comment> Core.BasicHeadlessSystem
This handles early setup of a headless image. If this activates, then BasicHeadfullGraphicsSystem will not. Instance Variables: notifier <Notifier-like-thing> What object should we install as Notifier current in order to deal with unhandled exceptions properly. This should be able to respond to #openException: and #openContext:label:proceedable. oldNotifier <Notifier-like-thing> If we replace the notifier with our own (by default HeadlessImage current) in order to handle headless exceptions, keep track of the old one so we can either put it back or delegate to it if necessary.
</comment> <class> <name>HeadlessFontPolicy</name> <environment>Graphics</environment> <super>Core.Object</super> <private>false</private> none <imports></imports> <category>Graphics-Fonts</category> <attributes> <package>Headless</package> </attributes> </class> <comment> Graphics.HeadlessFontPolicy
HeadlessFontPolicy stands in for the default FontPolicy behavior for a HeadlessScreen whenever an image has no WindowingSystem.
</comment> <class> <name>HeadlessError</name> <environment>Core</environment> <super>Core.Error</super> <private>false</private> none <imports></imports> <category>Headless-Support</category> <attributes> <package>Headless</package> </attributes> </class> <comment> Core.HeadlessError
The image is running headless, and this process has violated the rules of headlessness. Usually, by atttempting to access the display.
</comment> <class> <name>HeadlessScreen</name> <environment>Graphics</environment> <super>Graphics.Screen</super> <private>false</private> none <imports></imports> <category>Headless-Support</category> <attributes> <package>Headless</package> </attributes> </class> <comment> Graphics.HeadlessScreen
I am a subclass of Screen for the express purpose of not activating the Screen.
</comment> <name>QuitOnHeadlessError</name> <environment>Tools.Notifier</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <initializer>false</initializer> <attributes> <package>Headless</package> </attributes> <methods> Graphics.HeadlessFont <category>accessing</category>
ascent ^0.
descent ^0.
encode: aCharacter ^0
encodingType ^#'not for display'
height ^0.
isCompositeFont ^false
name ^'not for display'.
pixelSize ^0.
spaceWidth ^0
widthAt: anIndex ^0
widthOf: aCharacter ^0
widthTable ^#()
</methods> <methods> Graphics.HeadlessFont <category>displaying</category>
displayString: string from: start to: stop at: aPoint on: aGraphicsContext "Render the string onto the graphicsContext"
</methods> <methods> Graphics.HeadlessFont <category>testing</category>
isAccessible "Answer whether the font can currently be used for display" ^false
</methods> <methods> Graphics.HeadlessFont <category>installing</category>
installOn: aGraphicsContext
</methods> <methods> OS.AbstractStreamTranscript <category>accessing</category>
stream ^stream
stream: aStream stream := aStream
transcript ^transcript
transcript: aTextCollector transcript := aTextCollector
</methods> <methods> OS.AbstractStreamTranscript <category>private</category>
appendEntry [stream nextPutAll: transcript nextEntry asString. stream flush] on: Error do: [:ex | ex return].
updateContents "This is currently only used for the Transcript clear operation. We ignore this by default."
</methods> <methods> OS.AbstractStreamTranscript <category>initialize-release</category>
initialize transcript := Transcript.
</methods> <methods> OS.AbstractStreamTranscript <category>updating</category>
update: aParameter HeadlessImage isActive ifFalse: [^self]. aParameter == #appendEntry ifTrue: [^self appendEntry]. aParameter == #update ifTrue: [^self updateContents].
</methods> <methods> OS.AbstractStreamTranscript class <category>instance creation</category>
new "Answer a newly created and initialized instance." ^super new initialize
</methods> <methods> OS.FileTranscript <category>initialize-release</category>
release [stream close] on: Error do: [:ex | ex return].
</methods> <methods> OS.FileTranscript <category>accessing</category>
filename ^filename
filename: aFilename filename := aFilename asFilename. [stream := (filename withEncoding: #'utf-8') readAppendStream] on: Error do: [:ex | stream := NullStream new. ex return].
</methods> <methods> OS.FileTranscript class <category>instance creation</category>
named: aStringOrFilename ^self new filename: aStringOrFilename.
</methods> <methods> OS.StandardOutTranscript <category>initialize-release</category>
initialize super initialize. stream := OS.Stdout.
</methods> <methods> OS.StandardOutTranscript class <category>instance creation</category>
current current isNil ifTrue: [current := self new]. ^current.
</methods> <methods> Core.HeadlessImage <category>accessing</category>
isHeadless: aBoolean WindowingSystem canActivate: aBoolean not.
isTerminating: aBoolean isTerminating := aBoolean
shouldSaveHeadless ^shouldSaveHeadless.
shouldSaveHeadless: aBoolean shouldSaveHeadless := aBoolean. DeploymentOptionsSystem current suppressSplashScreenAndHerald: aBoolean.
stackDumpStream stackDumpStream isNil ifTrue: [^Transcript]. ^stackDumpStream
stackDumpStream: aWriteStream stackDumpStream := aWriteStream
startupFilename "Nil means no startup file whatsoever." ^startupFilename
startupFilename: aStringOrNil "Nil means no startup file whatsoever." startupFilename := aStringOrNil
suspendedProcesses suspendedProcesses isNil ifTrue: [suspendedProcesses := Dictionary new]. ^suspendedProcesses
transcriptFilename "Nil means no transcript file whatsoever." ^transcriptFilename
transcriptFilename: aStringOrNil "Nil means no transcript file whatsoever." transcriptFilename := aStringOrNil
transcriptToFile transcriptToFile isNil ifTrue: [transcriptToFile := false]. ^transcriptToFile.
transcriptToFile: aBoolean transcriptToFile := aBoolean
transcriptToFileHeadless transcriptToFileHeadless isNil ifTrue: [transcriptToFileHeadless := true]. ^transcriptToFileHeadless.
transcriptToFileHeadless: aBoolean transcriptToFileHeadless := aBoolean.
transcriptToStandardOut transcriptToStandardOut == nil ifTrue: [transcriptToStandardOut := false]. ^transcriptToStandardOut.
transcriptToStandardOut: aBoolean transcriptToStandardOut := aBoolean.
transcriptToStandardOutHeadless transcriptToStandardOutHeadless == nil ifTrue: [transcriptToStandardOutHeadless := true]. ^transcriptToStandardOutHeadless.
transcriptToStandardOutHeadless: aBoolean transcriptToStandardOutHeadless := aBoolean.
</methods> <methods> Core.HeadlessImage <category>saving</category>
saveHeadfull: prefix "Returns true if we just did the snapshot, false if we are restarting the image. This saves another image headfully, but we continue to run as the image we were before. It's different this way than a normal 'save as...' operation." ^self saveHeadless: false to: prefix.
saveHeadless: prefix "Returns true if we just did the snapshot, false if we are restarting the image. This saves another image headless, but we continue to run as the image we were before. It's different this way than a normal 'save as...' operation." ^self saveHeadless: true to: prefix.
saveHeadless: beHeadless to: prefix "Returns true if we just did the snapshot, false if we are restarting the image. Put our image prefix back the way it was if we're continuing to run." self shouldSaveHeadless: beHeadless. ^Snapshot new saveDetachedTo: prefix thenQuit: false
</methods> <methods> Core.HeadlessImage <category>private</category>
defaultDebugImageName ^ 'headless-debug'.
defaultStartupFilename ^ 'headless-startup.st'
defaultTranscriptFilename ^ 'headless-transcript.log'
</methods> <methods> Core.HeadlessImage <category>actions</category>
pauseAction super pauseAction. currentlyHeadless := self isHeadless. WindowingSystem canActivate: shouldSaveHeadless not.
readStartupFile | rcFile | startupFilename isNil ifTrue: [^self]. ImageConfigurationSystem allowFilein ifFalse: [^self]. rcFile := Filename named: startupFilename. (rcFile exists and: [rcFile isReadable]) ifTrue: [[rcFile fileIn] fork].
resumeAction super resumeAction. WindowingSystem canActivate: currentlyHeadless not. shouldSaveHeadless := currentlyHeadless.
setUp super setUp. shouldSaveHeadless := false. self isHeadless ifTrue: [ self readStartupFile].
</methods> <methods> Core.HeadlessImage <category>testing</category>
isActivationInProcess "Answer true if the system is running as a ``Smalltalk server'' within some process. Answer false if the system is running as a stand-alone Smalltalk environment. This will depend on whether the system was loaded as a DLL or shared library by some process, or not. If the primitive fails then presumably the engine does not support being used as a DLL or shared library, so in this case return false." <primitive: 1059> ^false
isHeadless WindowingSystem isActive ifTrue: [^false]. ^WindowingSystem canActivate not.
isTerminating ^isTerminating
shouldSendTranscriptToFile self transcriptFilename isNil ifTrue: [^false]. ^self isHeadless ifTrue: [self transcriptToFileHeadless] ifFalse: [self transcriptToFile]
shouldSendTranscriptToStandardOut ^self isHeadless ifTrue: [self transcriptToStandardOutHeadless] ifFalse: [self transcriptToStandardOut]
</methods> <methods> Core.HeadlessImage <category>initializing</category>
initialize super initialize. isTerminating := true. self transcriptFilename: self defaultTranscriptFilename. self startupFilename: self defaultStartupFilename. currentlyHeadless := true. shouldSaveHeadless := false. transcriptToStandardOut := false. transcriptToFile := false. transcriptToStandardOutHeadless := true. transcriptToFileHeadless := true.
setupTranscript "The Transcript is handled differently when the image is headless versus headful. In headless mode, the Transcript can go to either standard out, a file, or both" "First, clean out any old file transcripts" Transcript dependents do: [:each | (each isKindOf: FileTranscript) ifTrue: [Transcript removeDependent: each. each release]]. self shouldSendTranscriptToStandardOut ifTrue: [(Transcript dependents includes: StandardOutTranscript current) ifFalse: [Transcript addDependent: StandardOutTranscript current]] ifFalse: [Transcript removeDependent: StandardOutTranscript current]. self shouldSendTranscriptToFile ifTrue: [ Transcript addDependent: (FileTranscript named: self transcriptFilename)].
</methods> <methods> Core.HeadlessImage <category>exception handling</category>
openContext: haltContext label: aString proceedable: aBoolean ^self isHeadless ifTrue: [self dumpStackToTranscript: haltContext label: aString. self isTerminating ifTrue: [ObjectMemory quit] ifFalse: [Processor activeProcess terminateWithExtremePrejudice]] ifFalse: [self isActivationInProcess ifTrue: [Notifier checkDump: haltContext label: aString]. BasicHeadlessSystem current oldNotifier openContext: haltContext label: aString proceedable: aBoolean]
openException: anException "Act as a notifier, dumping stack" ^self openContext: thisContext label: anException errorString proceedable: anException willProceed.
</methods> <methods> Core.HeadlessImage <category>debugging</category>
becomeHeadfull "WARNING: May cause stability problems. This changes an image from headless to headful mode, manually running the things that need to be run in order to do this. Because we are running these things manually this is fragile code, and it won't take into account any possible user actions. However, it can be very useful in debugging, so we include it. See also ObjectMemory>>installSystemWithPriority:" | workspace message workspaceClass | self isHeadless ifFalse: [^self]. WindowingSystem canActivate: true. "We must explicitly activate the basic graphics, because the things that prereq them have already activated successfully" BasicHeadfullGraphicsSystem activate. WindowingSystem activate. DevelopmentSystem activate. self setupTranscript. Notifier beDevelopment. message := #headlessWarning << #headless >> 'WARNING: This image has been switched out of headless mode. It may be unstable. We recommend not saving this image and using it only for debugging. See HeadlessImage>>becomeHeadfull'. workspaceClass := (#{Tools.Workspace} ifDefinedDo: [:theClass | theClass] elseDo: [#{SimpleWorkspace} valueOrDo: [Transcript cr; show: message. ^self ]]). workspace := workspaceClass with: message labeled: #WARNING << #headless >> 'WARNING'. workspace open.
debug: text "Display the text on the Transcript, doing the right thing if it happens to be file based. This method is provided purely as a courtesy for debugging, and is not essential for headless operation." Transcript cr; show: text.
</methods> <methods> Core.HeadlessImage <category>checking head</category>
cannotSend "The image is running headless, and this process has violated the rules of headlessness. Raise the exception indicating a violation of headlessness. If the exception is not caught, suspend and save this process for later debugging. Optionally, save the image so it can be debugged." | now | [HeadlessError raise] on: Signal noHandlerSignal do: [:ex | ex return]. now := Time dateAndTimeNow. self suspendedProcesses at: now put: Processor activeProcess. Transcript cr; show: '-------------------'; print: now; show: '------'; cr; show: thisContext printStack; show: '---------------------------------------------------'; cr; endEntry. "Optionally save the image right now so it can be debugged." isTerminating ifTrue: [ [| justSnapped | justSnapped := self saveHeadfull: self defaultDebugImageName. justSnapped ifTrue: [ObjectMemory quit]] fork]. Processor activeProcess suspend
checkHeadless "This method is intended to be sent from those methods that should not be executed in a headless environment. If the image is not running headless, return without side-effect; otherwise, trigger the exception mechanism." self isHeadless ifTrue: [self cannotSend]
dumpStackToTranscript: aContext label: aString "Dump a stack trace to the Transcript starting at aContext. If the debugger or runtime packager dumper facilities are available, use them. Otherwise print a simple stack trace." (self dumpStackToTranscriptUsingDebuggerService: aContext label: aString) ifTrue: [^self]. (self dumpStackToTranscriptUsingRTPDumper: aContext label: aString) ifTrue: [^self]. self dumpStackToTranscriptBasic: aContext label: aString.
dumpStackToTranscriptBasic: aContext label: aString "Dump a stack trace to the Transcript starting at aContext." self stackDumpStream cr; nextPutAll: '---------------------------------------------------'; cr; nextPutAll: aString printString; cr; nextPutAll: aContext printStack; nextPutAll: '---------------------------------------------------'; cr; flush
dumpStackToTranscriptUsingDebuggerService: aContext label: aString "Dump a stack trace to the Transcript starting at aContext, using the PDP debugger's facilities, if they're present. Refer to them using a string so that we don't encourage the tracing mechanism to include them if it wouldn't otherwise do so." ^self dumpStackToTranscriptUsingDebuggerService: aContext label: aString stopWhen: nil.
dumpStackToTranscriptUsingDebuggerService: aContext label: aString stopWhen: aBlock "Dump a stack trace to the Transcript starting at aContext, using the PDP debugger's facilities, if they're present. Refer to them using a string so that we don't encourage the tracing mechanism to include them if it wouldn't otherwise do so." | debuggerService dumpPolicy shortList | debuggerService := Smalltalk at: 'DebuggerService' ifAbsent: [^false]. "Make up values for proceedable and interrupted. We're not planning to make use of them anyway, just dump a stack" [ | debugger output | debugger := debuggerService context: aContext proceedable: false interrupted: false. dumpPolicy := ContextDumpPolicy new. output := String new writeStream. dumpPolicy stream: output. dumpPolicy errorMessage: aString. shortList := self truncateContextList: debugger contextList using: aBlock. dumpPolicy stack: shortList. dumpPolicy numberToDump: shortList size. dumpPolicy printVerbose. self stackDumpStream nextPutAll: output contents; flush] on: Error do: [:ex | self dumpStackToTranscriptBasic: ex initialContext label: 'error printing stack: ', ex description asString. ^false]. ^true.
dumpStackToTranscriptUsingRTPDumper: aContext label: aString "Dump a stack trace to the Transcript starting at aContext using the Runtime Packager's runtime facilities. Refer to them using a string so that we don't encourage the tracing mechanism to include them if it wouldn't otherwise do so." | rtpDumper dumper | rtpDumper := Smalltalk at: 'RuntimePackager.RuntimeFullDumper' ifAbsent: [^false]. self stackDumpStream cr; show: aString printString. [dumper := rtpDumper new. dumper dumpStream: self stackDumpStream. dumper dumpExceptionReport: nil context: thisContext] on: Error do: [:ex | self dumpStackToTranscriptBasic: ex initialContext label: 'error printing stack: ', ex description asString. ^false]. ^true.
truncateContextList: aList using: aBlock "Truncate the list of contexts we are going to print based on some arbitrary criteria. The motivating example is to trim the stack at an unboundMethod, hiding the mechanisms of compiling and getting the code to run when they're not of interest." | newList | aBlock isNil ifTrue: [^aList]. newList := OrderedCollection new: aList size. aList do: [:each | (aBlock value: each) ifTrue: [ newList add: each. ^newList] ifFalse: [ newList add: each]]. ^newList.
</methods> <methods> Core.HeadlessImage <category>prerequisites</category>
prerequisiteSystems "On startup, all subsystems activating on #earlySystemInstallation will always start up before any that activate on #returnFromSnapshot. However, on shutdown there aren't two distinct events, so we add a prerequisite to ensure that at least the normal early installation systems will be available until the #returnFromSnapshot subsystems have finished shutting down." ^Array with: EarlyInterestNotificationSystem.
</methods> <methods> Core.HeadlessImage class <category>accessing</category>
default ^self current.
</methods> <methods> Core.HeadlessImage class <category>testing</category>
isHeadless ^self current isHeadless.
</methods> <methods> Core.BasicHeadlessSystem <category>actions</category>
setUp "Note that we explicitly don't call super setUp here, because our superclass is going to set up by activating exactly one of its subclasses" HeadlessImage isHeadless ifTrue: [HeadlessScreen preInstall. Notifier current == self headlessNotifier ifFalse: [oldNotifier := Notifier current]. Notifier current: self headlessNotifier] ifFalse: [ "If we're the ones who set the notifier differently, then put it back. Otherwise leave it alone" (Notifier current == self headlessNotifier) ifTrue: [Notifier current: oldNotifier]]. HeadlessImage current setupTranscript.
</methods> <methods> Core.BasicHeadlessSystem <category>accessing</category>
headlessNotifier ^headlessNotifier isNil ifTrue: [HeadlessImage current] ifFalse: [headlessNotifier].
headlessNotifier: aNotifier headlessNotifier := aNotifier
oldNotifier ^oldNotifier.
</methods> <methods> Core.BasicHeadlessSystem <category>testing</category>
canActivate ^super canActivate and: [HeadlessImage isHeadless].
</methods> <methods> Graphics.HeadlessFontPolicy <category>accessing</category>
defaultFont ^HeadlessFont new.
findFont: aQuery ^HeadlessFont new.
graphicsDevice ^HeadlessScreen default
preferredFontSize ^1.
</methods> <methods> Core.HeadlessError <category>defaults</category>
defaultMessageText ^(#exceptHeadlessError << #dialogs >> 'Attempted to access display in headless image').
</methods> <methods> Graphics.HeadlessScreen <category>accessing</category>
bounds "This message should never be sent when running headless." HeadlessImage default checkHeadless.
contentsFromUser "From super: Answer an Image with the contents of a user-specified area on my screen. The palette of the returned image may differ from the receiver's default color palette. For example, the captured image may potentially use pixel values that are unallocated in the default color palette." "Clients have no business sending this in a headless image." ^HeadlessImage default cannotSend
defaultColorPolicy ^PaintPolicy new
defaultFontPolicy ^HeadlessFontPolicy new
isOpen "From super: Answer whether the receiver is open." "Since we are headless, always answer false." ^false
</methods> <methods> Graphics.HeadlessScreen <category>user interaction</category>
dragShape: shape offset: offsetPoint gridPhase: gridPhasePoint gridSpacing: gridSpacingPoint boundedBy: boundsRectangleOrNil whileButton: button isDown: isDownBoolean "Override the Screen implementation for the purpose of trapping this operation when running headless" ^HeadlessImage default cannotSend
flush ^self
platformName ^'Unknown'.
</methods> <methods> Graphics.HeadlessScreen <category>initializing</category>
initialize "Don't call super initialize. Set the resolution, because it's hard-coded anyway" resolution := 75@75. self installPaintPolicies.
</methods> <methods> Graphics.HeadlessScreen class <category>system startup</category>
install "This method should be unnecessary because I assume that the only place #install is sent to Screen is in Screen>initialize. Let's test that assumption..." HeadlessImage default cannotSend
open: aNameOrNil "Link up to a display, permitting the creation of windows and pixmaps" "Only a single screen is currently supported." ^self new.
preSnapshot "From super: Prepare to snapshot" "When running headless, nothing needs to be done." ^self
</methods> <methods> Graphics.HeadlessScreen class <category>class initialization</category>
initialize "Do nothing. Note that Screen sends itself #install in its version of this method. Since we do not send #install here, we don't need to override it in this subclass." "HeadlessScreen initialize" ^self
</methods> <methods> Graphics.HeadlessScreen class <category>private</category>
registry ^Dictionary new.
</methods> <methods> Tools.Notifier class <category>private</category>
checkDump: aContext label: labelText "Check if we should dump a stack trace to a file." UHEFilename isNil ifTrue: [^self]. [| file | [file := UHEFilename asFilename newReadWriteStream. file cr; nextPutAll: 'DUMP:'; cr; nextPutAll: labelText; cr; cr. file nextPutAll: aContext printStack] ensure: [file close]] on: Object errorSignal do: [:ex| ex return]. "UHEFilename := 'uhedump.txt'. self checkDump: thisContext label: 'thisContext'. UHEFilename := nil"
</methods> <methods> Kernel.Process <category>changing process state</category>
terminateWithExtremePrejudice "Terminate the receiver process, by sending the Process terminateSignal. Handle and discard any errors encountered running unwind blocks." "If the receiver is the active process then raise the terminateSignal which should be caught by the handler in Process class>>forBlock:priority:. The handler will return, causing all unwind blocks to run, and then will invoke finalTerminate, actually terminating the receiver." Processor activeProcess == self ifTrue: [[Process terminateSignal raise] on: Error, UnhandledException do: [:ex| | unwindingContext | unwindingContext := thisContext findNextUnwindUpTo: nil. (unwindingContext notNil and: [unwindingContext sender notNil]) ifTrue: [thisContext terminateTo: unwindingContext sender] ifFalse: [ex return]]. ^self finalTerminate]. "If the receiver is not the active process and its suspendedContext is nil then it is already suspended." suspendedContext == nil ifTrue: [^self]. "Suspend the receiver, then place a block atop the receiver's stack to invoke this method as the active process, and resume the receiver." interruptProtect critical: [| savedContext interruptContext | myList == nil ifFalse: [self suspend]. savedContext := suspendedContext. interruptContext := [self terminateWithExtremePrejudice] newContext. interruptContext sender: savedContext. suspendedContext := interruptContext. self resume]
</methods> <methods> Kernel.ObjectMemory class <category>deprecated</category>
saveHeadless: beHeadless to: imageFilePrefix ^HeadlessImage default saveHeadless: beHeadless to: imageFilePrefix.
</methods> <methods> Core.HeadlessImage <category>command-line options</category>
listAllOptions "List all available command-line options in the system" <option: '-listOptions'> | sortedSubsystems options alreadyProcessedOptions | Stdout nextPutAll: 'VisualWorks command-line options summary (case-insensitive):'; cr. alreadyProcessedOptions := Set new. sortedSubsystems := Subsystem withAllSubclasses asSortedCollection: [:a :b | a name <= b name]. sortedSubsystems do: [:each | options := each current commandLineOptions. options := options reject: [:eachOption | alreadyProcessedOptions includes: eachOption option]. options := options asSortedCollection: [:a :b | a option <= b option]. options isEmpty ifFalse: [ Stdout cr; nextPutAll: ' ', each name, ':'; cr. options do: [:eachOption | Stdout nextPutAll: ' ', eachOption option; cr]]. options do: [:eachOption | alreadyProcessedOptions add: eachOption option]]. Stdout flush. ObjectMemory quit.
noStartupFile <option: '-nohlstrc'> startupFilename := nil.
noTerminateOnErrorOption <option: '-no-terminate-on-error'> self isTerminating: false.
startupFileName: aStream <option: '-hlstrc'> | fileNames | fileNames := CommandLineInterest argumentsFrom: aStream. fileNames isEmpty ifFalse: [ startupFilename := fileNames first].
terminateOnErrorOption <option: '-terminate-on-error'> self isTerminating: true.
</methods> <methods> Graphics.BasicGraphicsSystem <category>command-line options</category>
transcriptFileName: aStream <option: '-transcript'> | fileNames | fileNames := CommandLineInterest argumentsFrom: aStream. fileNames do: [:each | each asUppercase = 'STDOUT' ifTrue: [ HeadlessImage current transcriptToStandardOut: true; transcriptToStandardOutHeadless: true] ifFalse: [ HeadlessImage current transcriptToFile: true; transcriptToFileHeadless: true; transcriptFilename: each]]
nogui "Run without a windowing system" <option: '-nogui'> self headless.
</methods> <methods> Graphics.WindowingSystem <category>prerequisites</category>
headlessPrerequisite <prerequisites> ^Array with: HeadlessImage.
</methods> <methods> Tools.VisualLauncher <category>actions</category>
imageSaveHeadlessAs "Save a headless image under the name supplied by the user." <menuItem: #(#SaveHeadlessAsDot #menus 'Save Headless As...') nameKey: nil menu: #(#menuBar #file) position: 10.5> | prefix | prefix := Snapshot new getImagePrefix. prefix isEmpty ifTrue: [^self]. HeadlessImage current saveHeadless: prefix.
</methods> <methods> Graphics.BasicGraphicsSystem <category>command-line options</category>
headless "Run without a windowing system. Note that we allow setting headless/headfull from a command-line option, but only on real startup. If we're setting up one of these systems later on, ignore the option." <option: '-headless'> EarlyInterestNotificationSystem isActive ifFalse: [ HeadlessImage default isHeadless: true].
headful "Run with a windowing system. Note that we allow setting headless/headfull from a command-line option, but only on real startup. If we're setting up one of these systems later on, ignore the option." <option: '-headfull'> <option: '-headful'> EarlyInterestNotificationSystem isActive ifFalse: [ HeadlessImage default isHeadless: false].
gui "Run with a windowing system" <option: '-gui'> self headful.
</methods> <methods> Core.FinalizationSystem <category>prerequisites</category>
headlessPrerequisite <prerequisites> ^Array with: HeadlessImage.
</methods> <initialize> Graphics.HeadlessScreen </initialize> "Imported Classes:" self error: 'Attempting to file-in parcel imports. Choose terminate or close' <class> <name>Object</name> <environment>Core</environment> <super></super> <private>false</private> none <imports></imports> <category>Kernel-Objects</category> <attributes> <package>Kernel-Objects</package> </attributes> </class> <class> <name>Subsystem</name> <environment>Core</environment> <super>Core.Object</super> <private>false</private> none state canActivate prerequisites current <imports></imports> <category>System-Subsystems</category> <attributes> <package>System-Subsystems</package> </attributes> </class> <class> <name>WindowingSystem</name> <environment>Graphics</environment> <super>Core.Subsystem</super> <private>false</private> none <imports></imports> <category>OS-Window System</category> <attributes> <package>OS-Window System</package> </attributes> </class> <class> <name>Screen</name> <environment>Graphics</environment> <super>Graphics.HostGraphicsDevice</super> <private>false</private> none boundingBox subRegions resolution rendererName <imports></imports> <category>OS-Window System</category> <attributes> <package>OS-Window System</package> </attributes> </class> <class> <name>ImplementationFont</name> <environment>Graphics</environment> <super>Core.Object</super> <private>false</private> none <imports></imports> <category>Graphics-Fonts</category> <attributes> <package>Graphics-Fonts</package> </attributes> </class> <class> <name>Process</name> <environment>Kernel</environment> <super>Core.Link</super> <private>false</private> none suspendedContext priority myList depth hostThreadKey interruptProtect environment isSystem name debugger locale <imports></imports> <category>Kernel-Processes</category> <attributes> <package>Kernel-Processes</package> </attributes> </class> <class> <name>FinalizationSystem</name> <environment>Core</environment> <super>Core.Subsystem</super> <private>false</private> none <imports></imports> <category>System-Subsystems</category> <attributes> <package>System-Subsystems</package> </attributes> </class> <class> <name>BasicGraphicsSystem</name> <environment>Graphics</environment> <super>Core.Subsystem</super> <private>false</private> none <imports></imports> <category>OS-Window System</category> <attributes> <package>OS-Window System</package> </attributes> </class> <class> <name>Error</name> <environment>Core</environment> <super>Core.Exception</super> <private>false</private> none <imports></imports> <category>Kernel-Exception Handling</category> <attributes> <package>Kernel-Exception Handling</package> </attributes> </class> <class> <name>VisualLauncher</name> <environment>Tools</environment> <super>UI.ApplicationModel</super> <private>false</private> none menuBar toolBar textCollector toolDock <imports></imports> <category>Tools-Misc</category> <attributes> <package>Tools-Misc</package> </attributes> </class>