Did perhaps anyone also experience the weird situation where UI
processes (those of the WindowManagers) were all scheduled at a low priority (user background = 30) in a runtime image? I recently noticed this only because some complex edit tools ran into a deadlock (which they didn't in the development image). I assume the priority is supposed to be 50, not 30. How could that have happened? I'm not forking any background processes during the startup process. Arent't window processes to be scheduled on a fixed priority anyway, regardless which process opened the ApplicationModel? Completely puzzled. Andre P.S: I fixed it by forking a block at 50 that opens the first application window (which in turn spawns off all other windows). Anyway, I'd really like to understand why this happened. Debugging a runtime image is hell. |
That seems odd. 30 is userBackgroundPriority. That might
mean that for some reason it was being started from a process running at
that priority. But that isn't normal startup behaviour.
I might try putting in code to explicitly do a stack dump when userBackgroundPriority was called - that might be illuminating. At 03:12 PM 10/9/2007, Andre Schnoor wrote: Did perhaps anyone also experience the weird situation where UI processes (those of the WindowManagers) were all scheduled at a low priority (user background = 30) in a runtime image? I recently noticed this only because some complex edit tools ran into a deadlock (which they didn't in the development image). --
Alan Knight [|], Cincom Smalltalk Development
|
In reply to this post by Andre Schnoor
Alan Knight wrote:
That seems odd. 30 is userBackgroundPriority. That might mean that for some reason it was being started from a process running at that priority. But that isn't normal startup behaviour. Good idea. Another possibility could be the process survived the return from snapshot and continues doing all the startup stuff in the runtime image. BTW: Is there any meaningful use for running window processes at different priorities? Shouldn't they better all be started at userSchedulingPriority? Andre |
Andre One may want to run a window at a lower
priority when it is displaying some kind of background activity and you
don’t want it to interfere with user interaction in another window. Terry From: [hidden email] [mailto:[hidden email]] That seems odd. 30 is userBackgroundPriority. That
might mean that for some reason it was being started from a process running at
that priority. But that isn't normal startup behaviour.
|
In reply to this post by Andre Schnoor
Andre Schnoor wrote:
Alan Knight wrote:That seems odd. 30 is userBackgroundPriority. That might mean that for some reason it was being started from a process running at that priority. But that isn't normal startup behaviour. FYI: I Just found the solution: It was an automated build script that initiated image stripping at a lower priority (a SubSystem interpreting the command line). The process survived the snapshot and started the application in the runtime image -- at the old priority. In case there is the slightest doubt regarding strange behavior differences between development and runtime images, I would recommend putting this in the #startupApplication method (or very early in the startup code): Processor activeProcess priority == Processor userSchedulingPriority ifFalse:[ Dialog warn: 'Unexpected process priority for startup' ]. I guess all kind of automated build scripts may have a tendency to run into this issue. Andre |
In reply to this post by Andre Schnoor
I think there's
actually a bug in the interaction between WindowManager process creation, the
RTP startup command, and command-line processing handled by application
#returnFromSnapshot code. Any windows opened by the RTP startup command or
command-line processing will each open in their own WindowManager, each with its
own process at priority 50. This is regardless of the WindowManagerUsagePolicy,
and can cause errors -- e.g. if the application intended to use a single
WindowManager to keep things in a single "thread". That's what happened in our
case, where the command line arguments were being used to script a series of
operations: log in to a db, run a report, log out, exit.
I explain what
happens in detail below. Off the top of my head the best solution would be to
make the RTP process for #createAndSaveFinalImage have a WindowManager. That way
any windows opened by the RTP startup command, command-line arguments or
Subsystems will start in that same WindowManager process (or in new ones if the
default is set to MakeNewWindowManagerUsagePolicy).
Hopefully someone
better informed can check my diagnosis and suggestions!
Steve
The snapshot is made
by RTP within RuntimeStartupController>>controlTerminate, which forks
RuntimeManager createAndSaveFinalImage. This is thus in a separate process at
priority 50, forked from the main UI process. During the snapshot, it gets
boosted to priority 100 in #preSnapshot. On restart, it gets to
here:
Snapshot>>postSnapshotBootstrap
at the start we are at priority 100. We
successfully do
#earlySystemInstallation, set the priority back to 50, and start doing #returnFromSnapshot.
By prereqs,
UserApplication->RuntimeSystem->InterestNotificationSystem, whose #setUp
finishes with
ObjectMemory changed:
#returnFromSnapshot
The last-but-one dependent is our class which handles command-line arguments.
These will thus be handled at priority 50 in a process other than the "main" UI
process. However, this process may perhaps be considered to be the "main" one
now, since it is the one in which the snapshot took place, and there are no
other windows. But this
process doesn't have a WindowManager
in its environmentDictionary...
We can see
what happens then from the following test with Workspaces. Run
normally, "Workspace open" gives a window with the same process as the
workspace from which it was run, so opening several windows puts them all in the
same process. But what
happens when we a fork a process and have it open two Worskpaces?
| log |
log := [:proc | Transcript cr; show: 'p:', proc hash printString; tab; show: 'wm: ', (proc windowManager ifNotNil: [:wm | wm hash]) printString]. [ | w1 w2 |
log value: Processor activeProcess. w1 := Workspace open window. w2 := Workspace open window. log value: w1 windowProcess. log value: w2 windowProcess. log value: Processor activeProcess. ] fork This
results in w1 and w2 each in its own process, each as the only window in its process.
How does RTP open the startupClass?
It used to be with RuntimeManager class>>update: for
#returnFromSnapshot, set by doOneStepFinalImageSave, but now it uses
RuntimeApplicationStartupSystem, whose #main does the deed.
RuntimeApplicationStartupSystem is parallel to UserApplication, and so also
prereqs InterestNotificationSystem, so old
#returnFromSnapshot dependencies like our command-line processing will
always happen before the RTP startup
command. If the RTP startup command opens
a window, it will be launched by the same WindowManagerless snapshot process, so will also get
its own WindowManager and process.
|
Wow, thanks for the thorough analysis. I've created AR 53071
for this.
At 04:33 PM 10/10/2007, Steven Kelly wrote: I think there's actually a bug in the interaction between WindowManager process creation, the RTP startup command, and command-line processing handled by application #returnFromSnapshot code. Any windows opened by the RTP startup command or command-line processing will each open in their own WindowManager, each with its own process at priority 50. This is regardless of the WindowManagerUsagePolicy, and can cause errors -- e.g. if the application intended to use a single WindowManager to keep things in a single "thread". That's what happened in our case, where the command line arguments were being used to script a series of operations: log in to a db, run a report, log out, exit. --
Alan Knight [|], Cincom Smalltalk Development
|
In reply to this post by Andre Schnoor
Thanks for the AR,
Alan! I wouldn't be too sure the analysis is "thorough" though -- it's equally
likely to be just verbose and convoluted... I'm in awe of people on this list
who really understand and have an intuition for how processes interact in
parallel.
Steve
|
Just for your information:
This is how I changed my automated build system to work around the issue: The build system is based on a SubSystem interpreting command line options, queueing them into an OrderedCollection as Blocks and then performing the requested actions in the #setUp method. I changed the execution of these action blocks to use AutomatedBuildSystem>>runAndWaitFor: aBlock | sync | sync := Sempahore new. [ aBlock value. sync signal ] forkAt: Processor userSchedulingPriority. sync wait. This causes all "commands", including the image stripping and snapshots, to run at priority 50, even though the command line subsystem "setUp"runs at 30 (for whatever reason). For me, this fixed the problem. The runtime image now awakes at priority 50 for #startupApplication. HTH Andre |
At 05:21 AM 10/11/2007, Andre Schnoor wrote:
Just for your information: I think it's running at priority 30 because you told it to. In normal usage, it runs at the normal priority of 50. --
Alan Knight [|], Cincom Smalltalk Development
|
In reply to this post by Andre Schnoor
Alan Knight schrieb: At 05:21 AM 10/11/2007, Andre Schnoor wrote: OUCH, yes. Alan, you're right. I've got an initialization script (.st file) that sets up my clean images when filed in. I found it extremely difficult to snapshot from within a file being loaded, so I forked off the snapshot with a delay, such that it happens *after* the file was read -- at a lower priority. Hence the low priority went on from snapshot to snapshot .... surviving the whole build procedure. This is a nice example of where the lack of subject - object separation can lead to. Images actually should not deploy themselves by shooting off their legs etc. But considering the current technology, I can't see any better solution at the moment. It would be great if one was able to compile images as an object and write them to disk from scratch. Andre P.S: Still have no idea how to file in a script that does a snapshot at the end. Perhaps loading a String and evaluating it after the file was closed could be more viable. |
Andre Schnoor wrote:
> P.S: Still have no idea how to file in a script that does a snapshot at > the end. Perhaps loading a String and evaluating it after the file was > closed could be more viable. Common practice is to still fork the snapshot at the end of your script, just at the same priority. The script process doesn't really give up control by calling #fork, so as long as the new process doesn't get higher priority, the script should be able to finish running. And even if it doesn't finish, if the snapshot is the last thing in the script the script process will go away right after image start anyway. I never noticed any problems with this. |
In reply to this post by Andre Schnoor
From: Martin Kobetic [mailto:[hidden email]]
> Common practice is to still fork the snapshot at the end of > your script, just at the same priority. The script process > doesn't really give up control by calling #fork, so as long > as the new process doesn't get higher priority, the script > should be able to finish running. And even if it doesn't > finish, if the snapshot is the last thing in the script the > script process will go away right after image start anyway. I > never noticed any problems with this. Even if the snapshot is the last thing in the script you may well be surprised. Because you forked, the snapshotting process has no WindowManager. When restarting, command-line arguments and subsystem startup will be handled in that process. Thus any windows opened by them will each be in its own WindowManager with its own process. That will then be a different WindowManager and process from the one where your script ran. Steve |
In reply to this post by Andre Schnoor
At 03:58 AM 10/12/2007, Andre Schnoor wrote:
Alan Knight schrieb: Typically you'd just fork a process with a delay, rather than at a lower priority. I throw in a couple of second delay, to make sure that any other processing has had time to finish. It's crude, but it's very difficult to have a hook for something like that, where you really want to run last. First, you'd like to make sure that the process initiating startup has completely finished. So even if you had it signal a semaphore, you'd prefer that it also then went on to return, and it's very hard to know when it's done. I suppose you could do some kind of polling for that process to have disappeared, but that starts to get complicated. And of course, as soon as you add such a thing, you know that someone else will want to run after whatever came last. Realize that the way snapshotting works is that the process doing the snapshot just keeps running afterwards, and is the same process that does the startup handling. So you save the image, and whoever saved it, keeps running after the save operation. If you save and quit, it'll quit afterwards. But then the next time you start up the image, it'll initiate the startup processing. It's almost continuation-ish. --
Alan Knight [|], Cincom Smalltalk Development
|
In reply to this post by Andre Schnoor
That's what we do, the snapshot is the last line in the script, haven't had any problems yet. |
Free forum by Nabble | Edit this page |