Difference between revisions of "ShutdownProcess"

From ReactOS Wiki
Jump to: navigation, search
(Category: Ideas)
(page was very outdated and has to be re-written!)
Line 1: Line 1:
Taken from GvGs blog on login and shutdown processes.
To be documented...
Currently (Reactos 0.2.4 and lower) logout and shutdown isn't handled gracefully. User processes are not informed of the pending shutdown, only the kernel is properly shutdown. This needs to be rectified.
See {{rev|66275}}
The collective minds of ros-kernel describe the logout/shutdown process as follows:
* App (usually explorer) calls ExitWindowsEx()
* ExitWindowsEx() sends a message to CSRSS
''Done in reactos/dll/win32/user32/misc/exit.c''
* CSRSS impersonates the caller and sends a message to a hidden WinLogon window
''Done in reactos/subsystems/win32/csrss/win32csr/exitros.c : UserExitReactos''
* WinLogon checks if the caller has the required privileges
''Done in reactos/base/system/winlogon/sas.c : CheckForShutdownPrivilege''
* WinLogon enters pending log-out state
* WinLogon impersonates the interactive user and calls ExitWindowsEx() again, passing some special internal flags
''Done in reactos/base/system/winlogon/sas.c : HandleLogoff & LogoffShutdownThread''
* CSRSS loops over all processes of the interactive user (sorted by their SetProcessShutdownParameters() level), sending WM_QUERYENDSESSION and WM_ENDSESSION messages to its top-level windows. If the messages aren't processed within the timeout period (registry key HKCU\Control Panel\Desktop\HungAppTimeout), CSRSS will put up a dialog box asking if the process should be terminated. Using the registry key HKCU\Control Panel\Desktop\AutoEndTask you can specify that the dialog box shouldn't be shown and CSRSS should just terminate the thread. If the the WM_ENDSESSION message is processed but the thread doesn't terminate within the timeout specified by HKCU\Control Panel\Desktop\WaitToKillAppTimeout CSRSS will terminate the thread. When all the top-level windows have been destroyed CSRSS will terminate the process. If the process is a console process, CSRSS will send a CTRL_LOGOFF_EVENT to the console control handler on logoff. No event is sent on shutdown. If the handler doesn't respond in time the same activities as for GUI apps (i.e. display dialog box etc) take place. This also happens if the handler returns TRUE.
''Done in reactos/subsystems/win32/csrss/win32csr/exitros.c : InternalExitReactos''
* This ends the processing for the first ExitWindowsEx() call from WinLogon. Execution continues in WinLogon, which calls ExitWindowsEx() again to terminate COM processes in the interactive user's session.
* WinLogon stops impersonating the interactive user (whos processes are all dead by now). and enters logged-out state
''Done in reactos/base/system/winlogon/sas.c : LogoffShutdownThread''
* If the ExitWindowsEx() request was for a logoff, WinLogon sends a SAS event (to display the "press ctrl+alt+del") to the GINA. WinLogon then waits for the GINA to send a SAS event to login.
''Done in reactos/base/system/winlogon/sas.c : HandleExitWindows''
* If the ExitWindowsEx() request was for shutdown/restart, WinLogon calls ExitWindowsEx() again in the system process context.
''Done in reactos/base/system/winlogon/sas.c : HandleShutdown & LogoffShutdownThread''
* CSRSS goes through the motions of sending WM_QUERYENDSESSION/WM_ENDSESSION to GUI processes running in the system process context but won't display dialog boxes or kill threads/processes. Same for console processes, using the CTRL_SHUTDOWN_EVENT (see kernel32/misc/console.c line 42 DefaultConsoleCtrlHandler.). The Service Control Manager is one of these console processes and has a special timeout value WaitToKillServiceTimeout.
* WinLogon issues a "InitiateSystemShutdown" request to the SM (SMSS API # 1)
* the SM propagates the shutdown request to every environment subsystem it started since bootstrap time (still active ones, of course)
* each environment subsystem, on shutdown request, releases every resource it aquired during its life (processes, memory etc), then dies
* when every environment subsystem has gone to bed, the SM actually initiates the kernel and executive shutdown by calling NtShutdownSystem.
Although this is a pretty long list, I thought it wouldn't take long to implement. Boy, was I wrong :-) It's not really difficult, but it does use some stuff which isn't used very often by other parts of the system and which contained some buggy or unimplemented functions. On the bright side, I did learn a lot about security tokens, logon sessions etc. There are many details to work out, mostly by writing small test apps on MS Windows (Q: if you have an app with more than one top-level window, does each window get WM_QUERYENDSESSION notification? A: yes. Q: Are the timeouts reset for each notification or is there one big timeout for the process as a whole? A: one big timeout).
So, where are we at this moment (end of August 2004)? Well, the first few steps are implemented (basically notifying Winlogon about the end session request). I'm working on the notification of GUI applications right now, that's almost finished (it already puts up the "End Program Now?" dialog box). Notification of console apps shouldn't be that hard because of code reuse. Process termination is easy (just call TerminateProcess()...). I'm not sure about the next step (terminating COM processes running in the interactive user's session). How do I recognize those processes? I'll probably chicken out of this one for now and just put in a FIXME, since we don't have any COM processes running at this point anyway... I estimate it will take another month or so to finish this.
For the future, I want to do some work on winlogon, since it is rather messy at the moment to put it nicely. One of the improvements of ReactOS over Windows is that we have the capability to start up in console mode. Only when a GUI app is started will the screen switch to graphics mode. I'd like to consolidate this by introducing a "/CONSOLE" boot switch. When this switch is not present on the boot line, Winlogon will load the program specified by the "Shell" registry value, normally this will be (ROS) explorer, causing the screen to switch to graphics mode. With the boot switch present, Winlogon will load the program specified by the "ConsoleShell" registry value (to be added), which normally will be cmd.exe running in "blue screen" mode.
The same boot switch can also be used to prompt for login name and password. Our GINA (Graphical Identification and Authentication, the component which is responsible for the winlogon user interface) dll can check for the presence of the switch and present either a console-mode login prompt or a GUI prompt. Auto-login (using the "DefaultUserName" registry value) in implemented, as I don't want to type a (mostly useless at this moment) username/password every time I boot ReactOS for testing.
'''Shutdown''' (From "Inside Microsoft Windows 2000", page 204)
If someone is logged on and a process initiates a shutdown by calling the Win32 ''ExitWindowsEx'' function, a message is sent to Csrss instructing it to perform the shutdown. Csrss in turn impersonates the caller and sends a Window message to a hidden window owned by Winlogon telling it to perform a system shutdown. Winlogon then impersonates the currently logged on user (who might or might not have the same security context as the user who initated the system shutdown) and calls ''ExitWindowsEx'' with some special internal flags. Again, this call causes a message to be sent to Csrss requesting a system shutdown.
This time, Csrss sees that the request is from Winlogon and loops through all the processes in the logon session of the interactive user (again, not the user who requested a shutdown). For each process that owns a top-level window, Csrss sends the '''WM_QUERYENDSESSION''' message to each thread in the process that has a Window message loop. If the thread returns TRUE, the system shutdown can proceed. Csrss then sends the '''WM_ENDSESSION''' Windows message to the thread to request it to exit. Csrss waits the number of seconds defined in HKCU\Control Panel\Desktop\HungAppTimeout for the thread to exit. (The default is 5000 milliseconds.)
If the thread dosen't exit before the timeout, Csrss displays the hung-program dialog box shown in Figure 4-3.(You can disable this dialog box by changing the registry value HKCU\Control Panel\Desktop\AutoEndTasks to 1). This dialog box indicates that a program isn't shutting down in a timely manner and gives the user a choice of either killing the process or aborting the shutdown. (There is no timeout on this dialog box, which means that a shutdown request could wait forever at this point.)
If the thread does exit before the timeout, Csrss continues sending the '''WM_QUERYENDSESSION/WM_ENDSESSION''' message pairs to the other threads in the process that own windows. Once all threads that own windows in the process have exited, Csrss terminates the process and goes on the next process in the interactive session.
If Csrss finds a console application, it invokes the console control handler by sending the '''CTRL_LOGOFF_EVENT''' event. (Only service processes receive the '''CTRL_SHUTDOWN_EVENT''' event on shutdown.) If the handler returns FALSE, Csrss kills the process. If the handler returns TRUE or doesn't respond by the number of seconds defined by HKCU\Control Panel\Desktop\WaitToKillAppTimeout (the default is 20000 milliseconds), Csrss displays the hung-program dialog box shown in Figure 4-3.
Next, Winlogon calls ''ExitWindowsEx'' to have Csrss terminate any COM processes that are part of the interactive user's session.
At this point, all the processes in the interactive user's session have been terminated. Winlogon calls ''ExitWindowsEx'' again, but this time in the system process context, which again sends a message to Csrss, which looks at all the processes belonging to the system context and performs and sends the '''WM_QUERYENDSESSION/WM_ENDSESSION''' message to GUI threads (as before). Instead of sending '''CTRL_LOGOFF_EVENT''', however, it sends '''CTRL_SHUTDOWN_EVENT''' to console applications that have registered control handlers. Note that the SCM is a console program that does regiser a control handler. When it receives the shutdown request, it in turn sends the service shutdown control message to all services that registered for shutdown notification. For more details on service shutdown (such as the shutdown timeout Csrss uses for SCM), see the "Service" section on page 236 in Chapter 5.
Although Csrss performs the same timeout as when it was terminating the user processes, it doesn't display any dialog boxes and doesn't kill any process. (The registry values for the system process timeouts are taken from the default user profile.) These timeouts simply allow system processes a chance to clean up and exit before the system shuts down. Therefore, many system processes are in fact still running when the system shuts down, such as Smss, Winlogon, the SCM and Lsass.
Once Csrss has finished its pass notifying system processes that the system is shutting down, Winlogon finishes the shutdown process by calling the executive subsystem function ''NtShutdownSystem''. This function calls the function ''NtSetSystemPowerState'' to orchestrate the shutdown of drivers and the rest of the executive subsystem (Plug and Play manager, power manager, executive, I/O manager, configuration manager, and memory manager).
For example, ''NtSetSystemPowerState'' calls the I/O manager to send shutdown I/O packets to all device drivers that have requested shutdown notification. This action gives device drivers a chance to perform any special processing their device might require before Windows 2000 exits. The configuration manager flushes any modified registry data to disk, and the memory manager writes all modified pages containing file data back to their respective files. If the option to clear the paging file at shutdown is enabled, the memory manager clears the paging file at this time. The I/O manager is called a second time to inform the file system drivers that the system is shutting down. System shutdown ends in the power manager. The action the power manager takes depends on whether the user specified a shutdown, a reboot, or a power down.
'''Service Shutdown''' (From "Inside Microsoft Windows 2000", page 259)
When Winlogon calls the Win32 ''ExitWindowsEx'' function, ''ExitWindowsEx'' sends a message to Csrss, the Win32 subsystem process, to invoke Csrss's shutdown routine. Csrss loops through the active processes and notifies them that the system is shutting down. For every system process except the SCM, Csrss waits up to the number of seconds specified by HKU\.DEFAULT\Control Panel\Desktop\WaitToKillAppTimeout (which default is 20 seconds) for the process to exit before moving on to the next process. When Csrss encounters the SCM process, it also notifies it that the system is shutting down but employs a timeout sprcific to the SCM. Csrss recognizes the SCM using the process ID Csrss saved when the SCM registered with Csrss using the ''RegisterServiceProcess'' function during system initialization. The SCM's timeout differs from that of other processes because Csrss know that the SCM communicates with services that need to perform cleanup when they shutdown, and so an administrator might need to tune only the SCM's timeout. The SCM's timeout value resides in the HKLM\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout registry value, and it defaults to 20 seconds.
The SCM's shutdown handler is responsible for sending shutdown notifications to all the services that requested shutdown notification when they initialized with the SCM. The SCM function ''ScShutdownAllServices'' loops through the SCM services database searching for sevices desiring shutdown notification and sends each one a shutdown command. For each service to which it sends a shutdown command, the SCM records the value of the service's ''wait hint'', a value that a service also specifies when it registers with SCM. The SCM keeps track of the largest wait hint it receives. After sending the shutdown message, the SCM waits either until one of the services it notified of shutdown exits or until the time specified by the largest wait hint passed.
If the wait hint expires without a service exiting, the SCM determines whether one or more of the services it was waiting on to exit have sent a message to the SCM telling the SCM that the service is progressing in its shutdown process. If at least one service made progress, the SCM waits again for the duration of the wait hint. The SCM continues executing this wait loop until either all the services have exited or none of the services upon which it's waiting has notified it of progress within the wait hint period.
While the SCM is busy telling services to shut down and waiting for them to exit, Csrss waits for the SCM to exit. If Csrss's wait ends without the SCM having exited (the WaitToKillServiceTimeout time expires), Csrss simply moves on, continuing the shutdown process. Thus, services that fail to shut down in a timely manner are simply left running, along with the SCM, as the system shuts down. Unfortunately, there's no way for administrators to know whether they should raise the WaitToKillServiceTimeout value on systems where services aren't getting a chance to shut down completely before the system shuts down.

Latest revision as of 20:36, 14 September 2015

To be documented...

See r66275