terminal/doc/specs/#2563 - closeOnExit and Ter...

6.3 KiB

author created on last updated issue id
Dustin Howett @DHowett-MSFT 2019-07-19 2019-11-05 #2563

Improvements to CloseOnExit

Abstract

This specification describes an improvement to the closeOnExit profile feature and the ITerminalConnection interface that will offer greater flexibility and allow us to provide saner defaults in the face of unreliable software.

Conventions and Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

Inspiration

Other terminal emulators like ConEmu have a similar feature.

Solution Design

ITerminalConnection Changes

  • The TerminalConnection interface will be augmented with an enumerator and a set of events regarding connection state transitions.
    • enum TerminalConnection::ConnectionState
      • This enum attempts to encompass all potential connection states, even those which do not make sense for a local terminal.
      • The wide variety of values will be useful to indicate state changes in a user interface.
      • NotConnected: All new connections will start out in this state
      • Connecting: The connection has been initiated, but has not yet completed connecting.
      • Connected: The connection is active.
      • Closing: The connection is being closed (usually by request).
      • Closed: The connection has been closed, either by request or from the remote end terminating successfully.
      • Failed: The connection was unexpectedly terminated.
    • event StateChanged(ITerminalConnection, IInspectable)
      • (the IInspectable argument is recommended and required for a typed event handler, but it will bear no payload.)
    • event TerminalDisconnected will be removed, as it is replaced by StateChanged
    • NOTE: A conforming implementation MUST treat states as a directed acyclic graph. States MUST NOT be transitioned in reverse.
  • A helper class may be provided for managing state transitions.

TerminalControl Changes

  • As the decision as to whether to close a terminal control hosting a connection that has transitioned into a terminal state will be made by the application, the unexpressive Close event will be removed and replaced with a ConnectionStateChanged event.
  • event ConnectionStateChanged(TerminalControl, IInspectable) event will project its connection's StateChanged event.
  • TerminalControl's new ConnectionState will project its connection's State.
    • (this is indicated for an eventual data binding; see Future Considerations.)

Application and Settings

  1. The existing closeOnExit profile key will be replaced with an enumerated string key supporting the following values (behaviors):
    • always - a tab or pane hosting this profile will always be closed when the launched connection reaches a terminal state.
    • graceful - a tab or pane hosting this profile will be closed if and only if the launched connection reaches the Closed terminal state.
    • never - a tab or pane hosting this profile will not automatically close.
    • See the Compatibility section for information on the legacy settings transition.
    • The new default value for closeOnExit will be graceful.
  2. Pane will remain responsible for making the final determination as to whether it is closed based on the settings of the profile it is hosting.

UI/UX Design

  • The existing ITerminalConnection implementations will be augmented to print out interesting and useful status information when they transition into a Closed or Failed state.
    • Example (ConPTY connection)
      • The pseudoconsole cannot be opened, or the process fails to launch.
        [failed to spawn 'thing': 0x80070002], transition to Failed.
      • The process exited unexpectedly.
        [process exited with code 300], transition to Failed.
      • The process exited normally.
        [process exited with code 0], transition to Closed.
  • The final message will always be printed regardless of user configuration.
  • If the user's settings specify closeOnExit: never/false, the terminal hosting the connection will never be automatically closed. The message will remain on-screen.
  • If the user's settings specify closeOnExit: graceful/true, the terminal hosting the connection will automatically be closed if the connection's state is Closed. A connection in the Failed state will not be closed, and the message will remain on-screen.
  • If the user's settings specify closeOnExit: always, the terminal hosting the connection will be closed. The message will not be seen.

Capabilities

Accessibility

This will give users of all technologies a way to know when their shell has failed to launch or has exited with an unexpected status code.

Security

There will be no impact to security.

Reliability

Windows Terminal will no longer immediately terminate on startup if the user's shell doesn't exist.

Compatibility

There is an existing closeOnExit boolean key that a user may have configured in profiles.json. The boolean values should map as follows:

  • true -> graceful
  • false -> never

This will make for a clean transition to Windows Terminal's sane new defaults.

Performance, Power, and Efficiency

Potential Issues

There will be no impact to Performance, Power or Efficiency.

Future considerations

  • Eventually, we may want to implement a feature like "only close on graceful exit if the shell was running for more than X seconds". This puts us in a better position to do that, as we can detect graceful and clumsy exits more readily.
    • (potential suggestion: { "closeOnExit": "10s" }
  • The enumerator values for transitioning connection states will be useful for connections that require internet access.
  • Since the connection states are exposed through TerminalControl, they should be able to be data-bound to other Xaml elements. This can be used to provide discrete UI states for terminal controls, panes or tabs hosting terminal controls.
    • Example: a tab hosting a terminal control whose connection has been broken MAY display a red border.
    • Example: an inactive tab that reaches the Connected state MAY flash to indicate that it is ready.