Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CHE-1979: Fix closing terminal widget on typing "exit" or when user kills terminal process #3554

Merged
merged 1 commit into from
Jan 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions exec-agent/src/term/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ type ReadWriteRoutingFinalizer struct {
}

var (
upgrader = websocket.Upgrader{
ReadBufferSize: 1,
WriteBufferSize: 1,
upgrader = websocket.Upgrader {
CheckOrigin: func(r *http.Request) bool {
return true
},
Expand Down Expand Up @@ -253,17 +251,30 @@ func sendPtyOutputToConnection(conn *websocket.Conn, reader io.ReadCloser, final
log.Printf("Couldn't normalize byte buffer to UTF-8 sequence, due to an error: %s", err.Error())
return
}
if err = conn.WriteMessage(websocket.TextMessage, buffer.Bytes()); err != nil {
log.Printf("Failed to send websocket message: %s, due to occurred error %s", string(buffer.Bytes()), err.Error())

if err := writeToSocket(conn, buffer.Bytes(), finalizer); err != nil {
return
}

buffer.Reset()
if i < n {
buffer.Write(buf[i:n])
}
}
}

//we write message to websocket with help mutex finalizer to prevent send message after "close connection" message.
func writeToSocket(conn *websocket.Conn, bytes []byte, finalizer *ReadWriteRoutingFinalizer) error {
defer finalizer.Unlock()

finalizer.Lock()
if err := conn.WriteMessage(websocket.TextMessage, bytes); err != nil {
log.Printf("Failed to send websocket message: %s, due to occurred error %s", string(bytes), err.Error())
return err
}
return nil
}

func ptyHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
Expand Down Expand Up @@ -324,7 +335,16 @@ func closeConn(conn *websocket.Conn, finalizer *ReadWriteRoutingFinalizer) {

finalizer.Lock()
if !finalizer.writeDone {
conn.Close()
//to cleanly close websocket connection, a client should send a close
//frame and wait for the server to close the connection.
err := conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
log.Printf("Failed to send websocket close message: '%s'", err.Error())
}
if err := conn.Close(); err != nil {
fmt.Printf("Close connection problem: '%s'", err.Error())
}

finalizer.writeDone = true
fmt.Println("Terminal writer closed.")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,21 @@
import org.eclipse.che.ide.extension.machine.client.MachineLocalizationConstant;
import org.eclipse.che.ide.extension.machine.client.perspective.widgets.tab.content.TabPresenter;
import org.eclipse.che.ide.extension.machine.client.processes.AddTerminalClickHandler;

import org.eclipse.che.ide.websocket.WebSocket;
import org.eclipse.che.ide.websocket.events.ConnectionClosedHandler;
import org.eclipse.che.ide.websocket.events.ConnectionErrorHandler;
import org.eclipse.che.ide.websocket.events.ConnectionOpenedHandler;
import org.eclipse.che.ide.websocket.events.MessageReceivedEvent;
import org.eclipse.che.ide.websocket.events.MessageReceivedHandler;
import org.eclipse.che.ide.websocket.events.WebSocketClosedEvent;

import javax.validation.constraints.NotNull;

import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.FLOAT_MODE;
import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.NOT_EMERGE_MODE;
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAIL;
import static org.eclipse.che.ide.websocket.events.WebSocketClosedEvent.CLOSE_NORMAL;

/**
* The class defines methods which contains business logic to control machine's terminal.
Expand All @@ -54,7 +58,6 @@ public class TerminalPresenter implements TabPresenter, TerminalView.ActionDeleg

//event which is performed when user input data into terminal
private static final String DATA_EVENT_NAME = "data";
private static final String EXIT_COMMAND = "\nexit";
private static final int TIME_BETWEEN_CONNECTIONS = 2_000;

private final TerminalView view;
Expand Down Expand Up @@ -164,6 +167,22 @@ private void connectToTerminalWebSocket(@NotNull String wsUrl) {

socket = WebSocket.create(wsUrl);

socket.setOnMessageHandler(new MessageReceivedHandler() {
@Override
public void onMessageReceived(MessageReceivedEvent event) {
terminal.write(event.getMessage());
}
});

socket.setOnCloseHandler(new ConnectionClosedHandler() {
@Override
public void onClose(WebSocketClosedEvent event) {
if (CLOSE_NORMAL == event.getCode()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we close terminal if and only if CLOSE_NORMAL == event.getCode() ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because, in case abnormal closing launches onErrorHandler and we try reconnect to terminal...

terminalStateListener.onExit();
}
}
});

socket.setOnOpenHandler(new ConnectionOpenedHandler() {
@Override
public void onOpen() {
Expand All @@ -186,18 +205,6 @@ public void apply(String arg) throws OperationException {
socket.send(jso.serialize());
}
});
socket.setOnMessageHandler(new MessageReceivedHandler() {
@Override
public void onMessageReceived(MessageReceivedEvent event) {
String message = event.getMessage();

terminal.write(message);

if (message.contains(EXIT_COMMAND) && terminalStateListener != null) {
terminalStateListener.onExit();
}
}
});
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,12 @@ public void onAddTerminal(final String machineId, Object source) {
newTerminal.setListener(new TerminalPresenter.TerminalStateListener() {
@Override
public void onExit() {
onStopProcess(terminalNode);
terminals.remove(terminalId);
String terminalId = terminalNode.getId();
if (terminals.containsKey(terminalId)) {
onStopProcess(terminalNode);
terminals.remove(terminalId);
}
view.hideProcessOutput(terminalId );
}
});
}
Expand Down