dotnet / fsharp

The F# compiler, F# core library, F# language service, and F# tooling integration for Visual Studio
https://dotnet.microsoft.com/languages/fsharp
MIT License
3.83k stars 773 forks source link

dotnet fsi crashes with lines longer than terminal width #17215

Open greggyb opened 1 month ago

greggyb commented 1 month ago

When editing a line in FSI, and seemingly only when we've already used the height of the terminal in lines of input, the interpreter process crashes when a single line overflows the terminal width.

It also unreliably reproduces when the terminal screen is not full, but the most reliable reproduction needs the long line to be at the bottom of a terminal screen where history has rolled off the top of the terminal.

Repro steps

  1. Type to fill the terminal, or run commands so that your prompt ends up at the bottom of the terminal you're using.
  2. $ dotnet fsi
  3. Type a long line (sample below), longer than the number of columns in the terminal
  4. When you get past the terminal width, the interpreter process will crash

The sample below is running on Ubuntu 22.04 from official apt sources, but I can reproduce in the following environments:

  1. FreeBSD 13.2 + neovim terminal
  2. FreeBSD 13.2 + oksh + kitty terminal
  3. FreeBSD 13.2 + oksh + xfce4-terminal
  4. Ubuntu 22.04 + osh + Gnome terminal
  5. Ubuntu 22.04 + osh + kitty terminal
  6. Ubuntu 22.04 + bash + kitty terminal
  7. Ubuntu 22.04 + neovim terminal
  8. Ubuntu 22.04 + vim terminal

++Edit++: also under tmux as a terminal multiplexer

For vim and neovim terminals, I have reproduced both by sending lines from a script file with Ionide-vim and by typing directly into the terminal. I originally found this by means of sending script lines to the interpreter with Ionide-vim. I had a long line that only caused issues when I had created my fsi window in a vertical split (two panes side by side, so each is half the screen width); if I stacked the windows on top of one another instead (each has whole screen width), I did not have any issue. Repro followed from there.

$ ps -o comm= $$
bash
greg@mercury:~$ uname -a
Linux mercury 6.5.0-1023-oem #24-Ubuntu SMP PREEMPT_DYNAMIC Tue May  7 14:26:31 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
greg@mercury:~$ ps -o comm= $$
bash
greg@mercury:~$ dotnet --version
8.0.105
greg@mercury:~$ dotnet fsi

Microsoft (R) F# Interactive version 12.8.102.0 for F# 8.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> printfn "This is a very long sentence which I will type to overflow the boundary of the terminal and yield the error that I am talking about in this bug report. No holding down a key for me! System.PlatformNotSupportedException: Operation is not supported on this platform.
   at System.ConsolePal.set_BufferHeight(Int32 value)
   at <StartupCode$fsi>.$Console.writeChar@358(ReadLineConsole x, FSharpRef`1 rendered, Char c) in /build/dotnet8-z6Gph8/dotnet8-8.0.105-8.0.5/src/fsharp/artifacts/source-build/self/src/src/fsi/console.fs:line 359
   at <StartupCode$fsi>.$Console.read@544(ReadLineConsole x, StringBuilder input, FSharpRef`1 anchor, FSharpRef`1 rendered, FSharpRef`1 changed, FSharpRef`1 optionsCache, FSharpRef`1 current, Unit unitVar0) in /build/dotnet8-z6Gph8/dotnet8-8.0.105-8.0.5/src/fsharp/artifacts/source-build/self/src/src/fsi/console.fs:line 633
   at FSharp.Compiler.Interactive.ReadLineConsole.ReadLine() in /build/dotnet8-z6Gph8/dotnet8-8.0.105-8.0.5/src/fsharp/artifacts/source-build/self/src/src/fsi/console.fs:line 643
   at FSharp.Compiler.Interactive.Shell.-ctor@1453-151.Invoke() in /build/dotnet8-z6Gph8/dotnet8-8.0.105-8.0.5/src/fsharp/artifacts/source-build/self/src/src/Compiler/Interactive/fsi.fs:line 1458
Stopped due to error
Unhandled exception. System.PlatformNotSupportedException: Operation is not supported on this platform.
   at System.ConsolePal.set_BufferHeight(Int32 value)
   at <StartupCode$fsi>.$Console.writeChar@358(ReadLineConsole x, FSharpRef`1 rendered, Char c) in /build/dotnet8-z6Gph8/dotnet8-8.0.105-8.0.5/src/fsharp/artifacts/source-build/self/src/src/fsi/console.fs:line 359
   at <StartupCode$fsi>.$Console.read@544(ReadLineConsole x, StringBuilder input, FSharpRef`1 anchor, FSharpRef`1 rendered, FSharpRef`1 changed, FSharpRef`1 optionsCache, FSharpRef`1 current, Unit unitVar0) in /build/dotnet8-z6Gph8/dotnet8-8.0.105-8.0.5/src/fsharp/artifacts/source-build/self/src/src/fsi/console.fs:line 633
   at FSharp.Compiler.Interactive.ReadLineConsole.ReadLine() in /build/dotnet8-z6Gph8/dotnet8-8.0.105-8.0.5/src/fsharp/artifacts/source-build/self/src/src/fsi/console.fs:line 643
   at FSharp.Compiler.Interactive.Shell.-ctor@1453-151.Invoke() in /build/dotnet8-z6Gph8/dotnet8-8.0.105-8.0.5/src/fsharp/artifacts/source-build/self/src/src/Compiler/Interactive/fsi.fs:line 1458
greg@mercury:~$ 

Expected behavior

You should be able to type arbitrarily long lines into FSI (or at least a whole lot longer than one screen width) and it should interpret the code.

Actual behavior

Overflowing a terminal line causes the exception above. Sometimes, I have observed that instead of immediately throwing the exception, instead the cursor will wrap around to the beginning of the current line without a linefeed/newlline character (as if it were just executing a carriage return, but I have not validated the actual character codes being interpreted while typing), and the exception will only be thrown sometime after that. It can also get very confused about what quotes have been terminated when this specific behavior occurs. I cannot reliably reproduce the latter behavior, but it throws the same System.PlatformNotSupportedException: Operation is not supported on this platform. When the latter behavior occurs I do not get the full stack trace either.

Known workarounds

Write shorter code.

Related information

vim and nvim versions.

greg@mercury:~$ nvim --version
NVIM v0.11.0-dev
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3
Run "nvim -V1 -v" for more info
greg@mercury:~$ /usr/bin/vim.basic --version
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Mar 14 2024 09:05:11)
Included patches: 1-579, 1969, 580-1848, 4975, 5016, 5023, 5072, 2068, 1849-1854, 1857, 1855-1857, 1331, 1858, 1858-1859, 1873, 1860-1969, 1992, 1970-1992, 2010, 1993-2068, 2106, 2069-2106, 2108, 2107-2109, 2109-3995, 4563, 4646, 4774, 4895, 4899, 4901, 4919, 213, 1840, 1846-1847, 2110-2112, 2121
Modified by team+vim@tracker.debian.org
Compiled by team+vim@tracker.debian.org
Huge version without GUI.  Features included (+) or not (-):
+acl               +file_in_path      +mouse_urxvt       -tag_any_white
+arabic            +find_in_path      +mouse_xterm       -tcl
+autocmd           +float             +multi_byte        +termguicolors
+autochdir         +folding           +multi_lang        +terminal
-autoservername    -footer            -mzscheme          +terminfo
-balloon_eval      +fork()            +netbeans_intg     +termresponse
+balloon_eval_term +gettext           +num64             +textobjects
-browse            -hangul_input      +packages          +textprop
++builtin_terms    +iconv             +path_extra        +timers
+byte_offset       +insert_expand     -perl              +title
+channel           +ipv6              +persistent_undo   -toolbar
+cindent           +job               +popupwin          +user_commands
-clientserver      +jumplist          +postscript        +vartabs
-clipboard         +keymap            +printer           +vertsplit
+cmdline_compl     +lambda            +profile           +vim9script
+cmdline_hist      +langmap           -python            +viminfo
+cmdline_info      +libcall           +python3           +virtualedit
+comments          +linebreak         +quickfix          +visual
+conceal           +lispindent        +reltime           +visualextra
+cryptv            +listcmds          +rightleft         +vreplace
+cscope            +localmap          -ruby              +wildignore
+cursorbind        -lua               +scrollbind        +wildmenu
+cursorshape       +menu              +signs             +windows
+dialog_con        +mksession         +smartindent       +writebackup
+diff              +modify_fname      +sodium            -X11
+digraphs          +mouse             -sound             -xfontset
-dnd               -mouseshape        +spell             -xim
-ebcdic            +mouse_dec         +startuptime       -xpm
+emacs_tags        +mouse_gpm         +statusline        -xsmp
+eval              -mouse_jsbterm     -sun_workshop      -xterm_clipboard
+ex_extra          +mouse_netterm     +syntax            -xterm_save
+extra_search      +mouse_sgr         +tag_binary        
-farsi             -mouse_sysmouse    -tag_old_static    
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
  fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -Wdate-time -g -O2 -ffile-prefix-map=/build/vim-RPNH56/vim-8.2.3995=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -D_REENTRANT -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 
Linking: gcc -Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -o vim -lm -ltinfo -lselinux -lsodium -lacl -lattr -lgpm -L/usr/lib/python3.10/config-3.10-x86_64-linux-gnu -lpython3.10 -lcrypt -ldl -lm -lm 
greggyb commented 1 month ago

With more experimentation, it appears that this is specific to readline-enabled interpreters. Disabling readline with $ dotnet fsi --readline- seems to eliminate the error.

vzarytovskii commented 1 month ago

What's the version of sdk in use?

greggyb commented 1 month ago

Ubuntu:

$ dotnet --version
8.0.105

FreeBSD:

$ dotnet --version
8.0.100
greggyb commented 1 month ago

Extra context: Right now, due to a confluence of how FSAC and editors interact, working around this with the --readline- option has pretty negative knock-on effects for interactive programming with Ionide plugins.

A fix for the latter (FSAC issues with CLI options) will make the situation much more tenable for interactive development. Personally, I hope to get that PR raised tonight, as this is impacting my productivity.

After that fix, I think the situation will be much less severe. It certainly won't be a major concern for me, as the vast majority (99%) of my interactive use is sending lines from an editor to the interpreter via Ionide.

bmitc commented 1 month ago

This isn't to say that "it works on my machine" but rather to give further debug data point that this indeed seems specific to the terminal being used. On Windows 11 and Windows Terminal, FSI handles long lines. For example:

PowerShell 7.4.2
Loading personal and system profiles took 1605ms.
> dotnet fsi

Microsoft (R) F# Interactive version 12.8.200.0 for F# 8.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> printfn "This is a very long sentence which I will type to overflow the boundary of the terminal and yield the error
 that I am talking about in this bug report. No holding down a key for me! System.PlatformNotSupportedException: Opera
tion is not supported on this platform.asdflkajsfdaoiwejfoawjefoaijwefljawlkefjlakwjfelkajwveoijaoifjeoawjfeawljlvkjaw
kljfoeiawjfeoiawjfoejawoefjoajwfeioajwfeljaklvjelkajfeoaijwfeoiawjefoij";;
This is a very long sentence which I will type to overflow the boundary of the terminal and yield the error that I am talking about in this bug report. No holding down a key for me! System.PlatformNotSupportedException: Operation is not supported on this platform.asdflkajsfdaoiwejfoawjefoaijwefljawlkefjlakwjfelkajwveoijaoifjeoawjfeawljlvkjawkljfoeiawjfeoiawjfoejawoefjoajwfeioajwfeljaklvjelkajfeoaijwfeoiawjefoij
val it: unit = ()

Versions:

> dotnet fsi --version
Microsoft (R) F# Interactive version 12.8.200.0 for F# 8.0

> dotnet --version
8.0.204

Hopefully that's helpful.