---
author: Dustin Howett @DHowett-MSFT
created on: 2019-07-19
last updated: 2019-11-05
issue id: "#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](https://tools.ietf.org/html/rfc2119).

## 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.<br>`[failed to spawn 'thing': 0x80070002]`, transition to `Failed`.
        * The process exited unexpectedly.<br>`[process exited with code 300]`, transition to `Failed`.
        * The process exited normally.<br>`[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.
