The Swift REPL doesn't properly display certain characters on some Linux terminals

Hi everyone.

The Swift REPL fails to display certain characters on some terminals (for example, Ubuntu 20.04 is affected, but not Ubuntu 18.04). After the first line, some characters will simply not show up (like colons and braces), although they are inputted. Backspaces will also fail to clear any characters.

There are two bug reports that detail this issue: here and here.

I haven't found the root cause, but I did find a possible fix for it.

Function Editline::ConfigureEditor has an early return:

  if (m_editline && m_multiline_enabled == multiline)
    return;

The early return is taken every time except for the first call, and removing it actually fixes the issue. One possibility is that this function assumes that no other part of the code will change the configuration, but this assumption is being violated somewhere else. Since this issue doesn't affect all Linux terminals, another possibility is that the bug is on the terminal side and not LLDB (the fact that Ubuntu 18.04 works, but Ubuntu 20.04 doesn't, is an indicator this might be the case IMO).

I have no experience with this EditLine API though, so I'm unable to determine if the bug is in LLDB or not. And in the case it is, don't know what to look for and how to "properly" fix the issue.

Before pursuing a second solution though, I'd like to check with you guys if removing the early return is acceptable or not. If we come to the conclusion that the bug is not on LLDB's side, removing the early return on Linux only might be an acceptable solution? In the case that it isn't, could anyone help me figure out what could possibly be messing with the configuration?

1 Like

[SR-13885] REPL doesn't show certain characters, doesn't show inserted characters, and shows deleted characters on line 2 onwards · Issue #56283 · apple/swift · GitHub may also have the same cause.

I hope you can track down the cause for this and fix it. :crossed_fingers:

1 Like

Update:

It looks like the issue is related to the auto-formatting function that's bound to ":" and "}". Removing this binding "fixes" the issue as well (and, as stated previously, running the configuration function every time does as well).

I have yet to understand the root cause of the issue though. It doesn't look like either el_set/el_wset are called outside of the configuration function, so I'm finding it hard to understand why the first line works correctly and the following ones don't.

If anyone has any ideas I'd be happy to hear them.

I did some more digging. The problem seems to be related to the IOHandler's file properties.

The lldb_private::File class has three three booleans that are calculated lazily (m_is_interactive, m_is_real_terminal, m_supports_colors).

m_error_sp's (on IOHandler) booleans are being calculated after EditLine's configuration (inside REPL::IOHandlerInputComplete line 310). For reasons I have yet to understand, this is what's messing with terminal on Ubuntu 20.04. Making sure these booleans are intialized before the call to EditLine's constructor fixes the issue.

@Adrian_Prantl @vedantk do you have any insight on this? Would making the CalculateInteractiveAndTerminal function public and ensuring that's called before EditLine's connstructor be an acceptable solution?

cc @Teemperor (Raphael's done quite a bit of work on completion, and may have some insight)

I narrowed the problem down a bit more. The problem is the call to set_curterm after we configure the EditLine editor.

The call chain is:
REPL::IOHandlerInputComplete ->
File::GetIsTerminalWithColors ->
File::CalculateInteractiveAndTerminal ->
llvm::sys::Process::FileDescriptorHasColors ->
terminalHasColors ->
set_curterm

Which is why ensuring that File::CalculateInteractiveAndTerminal is called before Editline::ConfigureEditor solves it. Maybe libedit uses terminfo under the hood, and by calling set_curterm this messes up the configuration for libedit.

It looks like a workaround related to libedit exists on macOS (USE_SETUPTERM_WORKAROUND). Maybe we could add something similar on Linux?

This sounds reasonable. As said on IRC, feel free to create a LLVM review for that. Thanks!

1 Like