Skip to content

Commit

Permalink
fix: defunct process remains after shell exit
Browse files Browse the repository at this point in the history
add: special keys for terminal
  • Loading branch information
XZB-1248 committed Oct 20, 2022
1 parent f19f4ac commit c400acc
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 21 deletions.
41 changes: 32 additions & 9 deletions client/service/terminal/terminal_others.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"Spark/modules"
"Spark/utils"
"encoding/hex"
"errors"
"github.com/creack/pty"
"os"
"os/exec"
Expand All @@ -16,31 +15,38 @@ import (
)

type terminal struct {
escape bool
lastPack int64
event string
pty *os.File
cmd *exec.Cmd
}

var defaultShell = ``

func init() {
go healthCheck()
}

func InitTerminal(pack modules.Packet) error {
cmd := exec.Command(getTerminal())
// try to get shell
// if shell is not found or unavailable, then fallback to `sh`
cmd := exec.Command(getTerminal(false))
ptySession, err := pty.Start(cmd)
if err != nil {
defaultShell = getTerminal(true)
return err
}
termSession := &terminal{
cmd: cmd,
pty: ptySession,
event: pack.Event,
lastPack: utils.Unix,
escape: false,
}
terminals.Set(pack.Data[`terminal`].(string), termSession)
go func() {
for {
for !termSession.escape {
buffer := make([]byte, 512)
n, err := ptySession.Read(buffer)
buffer = buffer[:n]
Expand All @@ -49,6 +55,10 @@ func InitTerminal(pack modules.Packet) error {
}}, pack)
termSession.lastPack = utils.Unix
if err != nil {
if !termSession.escape {
termSession.escape = true
doKillTerminal(termSession)
}
common.WSConn.SendCallback(modules.Packet{Act: `TERMINAL_QUIT`}, pack)
break
}
Expand Down Expand Up @@ -148,21 +158,34 @@ func PingTerminal(pack modules.Packet) {
}

func doKillTerminal(terminal *terminal) {
terminal.escape = true
if terminal.pty != nil {
terminal.pty.Close()
}
if terminal.cmd.Process != nil {
terminal.cmd.Process.Kill()
terminal.cmd.Process.Wait()
terminal.cmd.Process.Release()
terminal.cmd.Process = nil
}
}

func getTerminal() string {
sh := []string{`/bin/zsh`, `/bin/bash`, `/bin/sh`}
for i := 0; i < len(sh); i++ {
_, err := os.Stat(sh[i])
if !errors.Is(err, os.ErrNotExist) {
return sh[i]
func getTerminal(sh bool) string {
shellTable := []string{`zsh`, `bash`, `sh`}
if sh {
shPath, err := exec.LookPath(`sh`)
if err != nil {
return `sh`
}
return shPath
} else if len(defaultShell) > 0 {
return defaultShell
}
for i := 0; i < len(shellTable); i++ {
shellPath, err := exec.LookPath(shellTable[i])
if err == nil {
defaultShell = shellPath
return shellPath
}
}
return `sh`
Expand Down
1 change: 1 addition & 0 deletions client/service/terminal/terminal_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ func doKillTerminal(terminal *terminal) {
(*terminal.stdin).Close()
if terminal.cmd.Process != nil {
terminal.cmd.Process.Kill()
terminal.cmd.Process.Wait()
terminal.cmd.Process.Release()
}
}
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/explorer.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ function FileBrowser(props) {

function renderOperation(file) {
let menus = [
{key: 'delete', name: i18n.t('EXPLORER.DELETE')},
{key: 'editAsText', name: i18n.t('EXPLORER.EDIT_AS_TEXT')},
{key: 'delete', name: i18n.t('EXPLORER.DELETE')},
];
if (file.type === 1) {
menus.pop();
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/procmgr.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ function ProcessMgr(props) {
destroyOnClose={true}
modalTitle={i18n.t('PROCMGR.TITLE')}
footer={null}
width={400}
width={500}
bodyStyle={{
padding: 0
}}
Expand Down
41 changes: 31 additions & 10 deletions web/src/components/terminal.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {createRef, useCallback, useEffect} from "react";
import React, {createRef, useCallback} from "react";
import {Button, Dropdown, Menu, message, Space} from "antd";
import {Terminal} from "xterm";
import {WebLinksAddon} from "xterm-addon-web-links";
Expand Down Expand Up @@ -290,7 +290,6 @@ function TerminalModal(props) {
}
input = String.fromCharCode(charCode);
}
console.log(CryptoJS.enc.Hex.stringify(CryptoJS.enc.Utf8.parse(input)));
sendData({
act: 'TERMINAL_INPUT',
data: {
Expand Down Expand Up @@ -378,7 +377,7 @@ class ExtKeyboard extends React.Component {
super(props);
this.visible = props.visible;
if (!this.visible) return;
this.fnKeys = [
this.funcKeys = [
{key: '\x1B\x4F\x50', label: 'F1'},
{key: '\x1B\x4F\x51', label: 'F2'},
{key: '\x1B\x4F\x52', label: 'F3'},
Expand All @@ -392,9 +391,26 @@ class ExtKeyboard extends React.Component {
{key: '\x1B\x5B\x32\x33\x7E', label: 'F11'},
{key: '\x1B\x5B\x32\x34\x7E', label: 'F12'},
];
this.fnMenu = (
<Menu onClick={this.onFnKey.bind(this)}>
{this.fnKeys.map(e =>
this.specialKeys = [
{key: '\x1B\x5B\x31\x7E', label: 'HOME'},
{key: '\x1B\x5B\x32\x7E', label: 'INS'},
{key: '\x1B\x5B\x33\x7E', label: 'DEL'},
{key: '\x1B\x5B\x34\x7E', label: 'END'},
{key: '\x1B\x5B\x35\x7E', label: 'PGUP'},
{key: '\x1B\x5B\x36\x7E', label: 'PGDN'},
];
this.funcMenu = (
<Menu onClick={this.onKey.bind(this)}>
{this.funcKeys.map(e =>
<Menu.Item key={e.key}>
{e.label}
</Menu.Item>
)}
</Menu>
);
this.specialMenu = (
<Menu onClick={this.onKey.bind(this)}>
{this.specialKeys.map(e =>
<Menu.Item key={e.key}>
{e.label}
</Menu.Item>
Expand All @@ -408,12 +424,12 @@ class ExtKeyboard extends React.Component {
this.setState({ctrl: !this.state.ctrl});
this.props.onCtrl(!this.state.ctrl);
}
onKey(e) {
this.props.onExtKey(e.key, false);
}
onExtKey(key) {
this.props.onExtKey(key, true);
}
onFnKey(e) {
this.props.onExtKey(e.key, false);
}

setCtrl(val) {
this.setState({ctrl: val});
Expand Down Expand Up @@ -464,7 +480,12 @@ class ExtKeyboard extends React.Component {
</Button>
</>
<Dropdown.Button
overlay={this.fnMenu}
overlay={this.specialMenu}
>
{i18n.t('TERMINAL.SPECIAL_KEYS')}
</Dropdown.Button>
<Dropdown.Button
overlay={this.funcMenu}
>
{i18n.t('TERMINAL.FUNCTION_KEYS')}
</Dropdown.Button>
Expand Down
1 change: 1 addition & 0 deletions web/src/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"TERMINAL.TITLE": "Terminal",
"TERMINAL.CREATE_SESSION_FAILED": "Failed to create terminal session",
"TERMINAL.SESSION_CLOSED": "Terminal session closed",
"TERMINAL.SPECIAL_KEYS": "Special Keys",
"TERMINAL.FUNCTION_KEYS": "Function Keys",

"DESKTOP.TITLE": "Desktop",
Expand Down
1 change: 1 addition & 0 deletions web/src/locale/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"TERMINAL.TITLE": "终端",
"TERMINAL.CREATE_SESSION_FAILED": "终端会话创建失败",
"TERMINAL.SESSION_CLOSED": "终端会话已关闭",
"TERMINAL.SPECIAL_KEYS": "特殊键",
"TERMINAL.FUNCTION_KEYS": "功能键",

"DESKTOP.TITLE": "桌面",
Expand Down

0 comments on commit c400acc

Please sign in to comment.