Bug 6157 - Mono.Terminal.LineEditor.UpdateHomeRow() throws System.DivideByZeroException when used under bash under rxvt on Windows
Summary: Mono.Terminal.LineEditor.UpdateHomeRow() throws System.DivideByZeroException ...
Status: NEW
Alias: None
Product: Compilers
Classification: Mono
Component: C# (show other bugs)
Version: unspecified
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Miguel de Icaza [MSFT]
URL:
Depends on:
Blocks:
 
Reported: 2012-07-17 10:59 UTC by Nathan Phillip Brink (binki)
Modified: 2016-03-14 02:28 UTC (History)
4 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
set.txt (3.56 KB, text/plain)
2012-07-23 11:19 UTC, Nathan Phillip Brink (binki)
Details

Description Nathan Phillip Brink (binki) 2012-07-17 10:59:46 UTC
binki@FT393D1 ~
$ uname -a
MINGW32_NT-5.1 FT393D1 1.0.17(0.48/3/2) 2011-04-24 23:39 i686 Msys

binki@FT393D1 ~
$ mono --version
Mono JIT compiler version 2.11.2 (master/f4d96d2)
Copyright (C) 2002-2012 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
        TLS:           normal
        SIGSEGV:       normal
        Notification:  Thread + polling
        Architecture:  x86
        Disabled:      none
        Misc:          softdebug 
        LLVM:          supported, not enabled.
        GC:            Included Boehm (with typed GC and Parallel Mark)

binki@FT393D1 ~
$ csharp
csharp>  
Unhandled Exception: System.DivideByZeroException: Division by zero
  at Mono.Terminal.LineEditor.UpdateHomeRow (Int32 screenpos) [0x00000] in <filename unknown>:0 
  at Mono.Terminal.LineEditor.Render () [0x00000] in <filename unknown>:0 
  at Mono.Terminal.LineEditor.InitText (System.String initial) [0x00000] in <filename unknown>:0 
  at Mono.Terminal.LineEditor.Edit (System.String prompt, System.String initial) [0x00000] in <filename unknown>:0 
  at Mono.CSharpShell.GetLine (Boolean primary) [0x00000] in <filename unknown>:0 
  at Mono.CSharpShell.ReadEvalPrintLoopWith (Mono.ReadLiner readline) [0x00000] in <filename unknown>:0 
  at Mono.CSharpShell.ReadEvalPrintLoop () [0x00000] in <filename unknown>:0 
  at Mono.CSharpShell.Run (System.String[] startup_files) [0x00000] in <filename unknown>:0 
  at Mono.Driver.Main (System.String[] args) [0x00000] in <filename unknown>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.DivideByZeroException: Division by zero
  at Mono.Terminal.LineEditor.UpdateHomeRow (Int32 screenpos) [0x00000] in <filename unknown>:0 
  at Mono.Terminal.LineEditor.Render () [0x00000] in <filename unknown>:0 
  at Mono.Terminal.LineEditor.InitText (System.String initial) [0x00000] in <filename unknown>:0 
  at Mono.Terminal.LineEditor.Edit (System.String prompt, System.String initial) [0x00000] in <filename unknown>:0 
  at Mono.CSharpShell.GetLine (Boolean primary) [0x00000] in <filename unknown>:0 
  at Mono.CSharpShell.ReadEvalPrintLoopWith (Mono.ReadLiner readline) [0x00000] in <filename unknown>:0 
  at Mono.CSharpShell.ReadEvalPrintLoop () [0x00000] in <filename unknown>:0 
  at Mono.CSharpShell.Run (System.String[] startup_files) [0x00000] in <filename unknown>:0 
  at Mono.Driver.Main (System.String[] args) [0x00000] in <filename unknown>:0 

binki@FT393D1 ~
$ echo ${TERM}
msys

Error does not happen when running from the cmd.exe terminal emulator.
Comment 1 Zoltan Varga 2012-07-18 03:41:23 UTC
-> mcs.
Comment 2 Miguel de Icaza [MSFT] 2012-07-23 10:10:05 UTC
Would you mind reporting the output of the "set" command on your terminal?
Comment 3 Miguel de Icaza [MSFT] 2012-07-23 10:10:49 UTC
Likely the msys package does not contain the terminfo information that allows us to compute the right terminal size.
Comment 4 Miguel de Icaza [MSFT] 2012-07-23 11:04:35 UTC
Can you compile and run this C program on your system?

#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>

int main ()
{
	struct winsize ws;
	int ret;
	
	if (ioctl (STDIN_FILENO, TIOCGWINSZ, &ws) == 0){
                printf ("%d %d\n", ws.ws_col, ws.ws_row);
                return 0;
	} 
        printf ("ioctl failed\n");
        return 1;
}
Comment 5 Nathan Phillip Brink (binki) 2012-07-23 11:19:09 UTC
Created attachment 2246 [details]
set.txt

This is the output of running `set' in the affected terminal.
Comment 6 Nathan Phillip Brink (binki) 2012-07-23 11:20:55 UTC
In response to comment 4 by miguel@xamarin.com
> Can you compile and run this C program on your system?

No, mingw32 doesn't include ioctl() because Windows doesn't have it.
Comment 7 Miguel de Icaza [MSFT] 2012-07-23 11:36:53 UTC
Can you try this C# sample instead?

Compile and run with Mono, it wont produce the expected results with .NET:

using System;
using System.Reflection;

class X {
	static void Main ()
	{
		var j = Console.WindowWidth;
		var fi = Type.GetType ("System.ConsoleDriver").GetField ("driver", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
		Console.WriteLine ("driver={0}", fi.GetValue (null));
	}
}
Comment 8 Nathan Phillip Brink (binki) 2012-07-23 11:43:11 UTC
In response to comment 7 by miguel@xamarin.com
> Can you try this C# sample instead?
> 
> Compile and run with Mono, it wont produce the expected results with .NET:

binki@FT393D1 ~
$ mcs -out:test test.cs

binki@FT393D1 ~
$ mono test
driver=System.NullConsoleDriver


Running under MS.net just for fun:

binki@FT393D1 ~
$ mv test{,.exe}

binki@FT393D1 ~
$ ./test.exe 

Unhandled Exception: System.IO.IOException: The handle is invalid.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
   at System.Console.get_WindowWidth()
   at X.Main()
Signal 67
Comment 9 Miguel de Icaza [MSFT] 2012-07-23 12:45:19 UTC
Can you find out what did Mono link against in the mono/mono/metadata directory?

Did it link against console-null.c, console-win32.c or console-unix.c?
Comment 10 Nathan Phillip Brink (binki) 2012-07-23 13:15:57 UTC
In reply to comment 9 by miguel@xamarin.com
> Can you find out what did Mono link against in the mono/mono/metadata
> directory?

binki@FT393D1 ~/My Documents/repos/Main
$ grep -aoe '.*console-.*' '/c/Program Files/Mono-2.11.2/lib/libmono-2.0.a'
libmonoruntime_la-console-win32.o/

It's a pre-built binary, so it's a bit difficult to determine that.
Comment 11 Miguel de Icaza [MSFT] 2012-07-23 14:36:32 UTC
Thanks, can you now trying running this C# program with Mono again, and inside the rxvt terminal that you are using.   Do not use .NET:

using System;
using System.Reflection;

class X {
	static int Main ()
	{
		var mi = Type.GetType ("System.ConsoleDriver").GetMethod ("get_IsConsole", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
		if (mi == null)
			return 2;
		var r = (bool) mi.Invoke (null, null);
		return r ? 0 : 1;
	}
}

Then compile and run like this:
$ gmcs a.cs
$ mono a.exe; echo $?

It should print 0, 1 or 2.
Comment 12 Nathan Phillip Brink (binki) 2012-07-23 14:42:26 UTC
In response to comment 11 by miguel@xamarin.com

binki@FT393D1 ~
$ gmcs a.cs

binki@FT393D1 ~
$ mono a.exe

binki@FT393D1 ~
$ echo $?
1
Comment 13 cydhaselton 2015-06-13 19:06:46 UTC
Out of curiosity was this fixed? I'm experiencing a similar error.
Comment 14 IBIT.ZEE 2015-07-02 15:32:21 UTC
Experiencing similar error runnning inside Cygwin64

Download source code, 
compiled sources, OK  // --prefix=/usr/mono --host=i686-pc-mingw32
Compiled and run test samples, OK

When invoking the repl "csharp" similar error arises...

-----
1st C# test result
Unhandled Exception: System.IO.IOException: The handle is invalid.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
   at System.Console.get_WindowWidth()
   at X.Main()


-----
2nd C#-test result
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at X.Main()
Segmentation fault

?any ideas / solutions
i'd like very much to have the REPL working in Cygwin
Comment 15 Nathan Phillip Brink (binki) 2016-03-05 19:21:49 UTC
Still broken for me, though now I have mintty instead of rxvt and MSYS2 instead of MSYS ;-). http://imgur.com/UzCLIUb . It’s like mono somehow detects it should run interactively but assumes that when it’s running interactively it can use the weird Windows APIs for discovering a cmd’s dimensions.

Let’s see how .net itself handles that (below). Looks like .net’s docs say that it should be impossible to set the Console.WindowWidth or Console.WindowHeight to 0 (that would throw an ArgumentOutOfRangeException), yet mono is willing to *return* 0 for those properties. And .net docs suggest that the API is liable to throw IOException when IsOutputRedirected is true. Seems like maybe instead of reporting a console size of 0,0, mono should be throwing an IOException when accessing that property like .net does? And, the REPL code should check IsOutputRedirected=true before trying to determine the console width. The REPL should operate without any assumptions about console dimensions when IsOutputRedirected=true because the console dimensions are meaningless in that case (e.g., piping output to a file or using either a dumb terminal or one that it is too dumb to understand).

ohnob@DESKTOP-A4G2C0J MSYS ~/OneDrive/Documents/Visual Studio 2015/Projects/ConsoleDimensions/ConsoleDimensions
$ cat Program.cs
using System;

class Program
{
    static int Main(string[] args)
    {
        Console.WriteLine($"{nameof(Console.IsOutputRedirected)}={Console.IsOutputRedirected}");
        Console.WriteLine($"{Console.WindowWidth},{Console.WindowHeight}");

        return 0;
    }
}

ohnob@DESKTOP-A4G2C0J MSYS ~/OneDrive/Documents/Visual Studio 2015/Projects/ConsoleDimensions/ConsoleDimensions
$ bin/Debug/ConsoleDimensions.exe
IsOutputRedirected=True

Unhandled Exception: System.IO.IOException: The handle is invalid.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
   at System.Console.get_WindowWidth()
   at Program.Main(String[] args) in c:\users\ohnob\onedrive\documents\visual studio 2015\Projects\ConsoleDimensions\ConsoleDimensions\Program.cs:line 8

ohnob@DESKTOP-A4G2C0J MSYS ~/OneDrive/Documents/Visual Studio 2015/Projects/ConsoleDimensions/ConsoleDimensions
$ mono bin/Debug/ConsoleDimensions.exe
IsOutputRedirected=True
0,0
Comment 16 Miguel de Icaza [MSFT] 2016-03-13 22:06:27 UTC
Likely this is a case of the console assuming that running on Windows, means running on the Windows console.
Comment 17 Miguel de Icaza [MSFT] 2016-03-13 22:10:17 UTC
You can try editing mono/mcs/class/System/ConsoleDriver.cs and in the static constructor, swap the checks in the static constructor so the TERM environment variable is used before the CreateWindowsConsoleDriver is used.

That will likely get you further, then report on what fails with that.
Comment 18 Miguel de Icaza [MSFT] 2016-03-14 02:28:12 UTC
The trick is to be able to reliably detect that we are running on Windows, but not on a windows-like shell window.

I do not think I should rely purely on "TERM" being set to determine that.   What is the Windows idiom to detect the condition whether the code is running in a CMD console or not?

Note You need to log in before you can comment on or make changes to this bug.