GNOME Bugzilla – Bug 588828
gio should have a Console class
Last modified: 2018-05-24 11:55:39 UTC
It'd be useful if gio had a class explicitly representing "the console", i.e. the controlling terminal on unix, and the win32 console streams on win32. Something roughly like http://java.sun.com/javase/6/docs/api/java/io/Console.html probably.
ya! srsly!
Actually, just to verify: we're talking about stdin/out here, right -- not /dev/tty?
And what's wrong with stdin and stdout then, if that is what we are talking about, and not /dev/tty? I don't think Java's (or .NET's) "Console" is a reason to introduce something similar in GLib. It has always seemed a bit silly to me that "Console" there actually means "whatever stdin or stdout is (re)directed from/to". The "Console" name would make me think of something curses-like or whatever to access the terminal (emulator) associated with /dev/tty, or on Windows its concept of console window.
I share tmls sentiment here.
Both use cases make sense. I guess we should probably have some sort of g_input_stream_new_for_stdin() and g_output_stream_new_for_std{out,err}() or something like that. If we want to do /dev/tty-style console properly (and I'm not sure its necessary) then we could have a GIOStream for that.
ttys are in scope; when connected to a tty, the GIOConsole would have a few high level operations like g_console_read_password ().
I did some work on this here: http://git.gnome.org/browse/libgsystem/commit/?id=87bf968f3470657e5a80d3f937b2142f9f6fb53b It has a real-world user: http://git.gnome.org/browse/ostree/commit/?id=6fde0b61a8987c93d6177d5163a5ef4144d47b56
As singletons, the console class and stdin/out/err streams probably ought to be thread-safe. (The streams already are I guess, assuming you don't make any of the changes mentioned below.) It seems weird to have static methods for some things, but a singleton with instance methods for other things. It also seems weird to have a stdout stream that doesn't implement printf. :) Which leads to the thought: should stdout and stderr get automatically wrapped in GDataOutputStreams, and stdin in a GDataInputStream? (Not that GDataOutputStream implements printf either, but it could...). In particular, if we don't have a single canonical buffered stdin/stdout, then different parts of code might create their own wrapper buffered streams around them, and then the fact that they have separate buffers will lead to wackiness (especially on the input stream, where there's no way to "unflush" any buffered input). Alternatively, if you didn't want them to be always buffered, you could have separate get_stdout() and get_buffered_stdout(), but they'd be linked together so that if you wrote something to the non-buffered stdout, it would automatically flush the buffered stdout first, and if you read from the non-buffered stdin, it would read the remaining buffered stdin first. Or just have APIs to turn buffering on/off on a single stream... And then, if the streams are going to be clever like that, then you could move the status line API onto GStdoutStream, and remove the _end_status_line method, because the stdout stream itself would know when it was doing a status line, and could just stop as soon as you did a non-status-line write. And the password API could be g_stdin_stream_read_password(), and then you don't need the console class at all... OTOH, I note that you didn't port any of the non-status-line g_print()s in ostree to use the stdout stream, so maybe this is all irrelevant because people mostly won't be using the streams as a replacement for the existing stdio APIs and so we don't have to worry about these use cases.
You're totally right about thread safety - g_print() is threadsafe today because it calls into FILE * which in glibc is thread safe by default. Buffering is a complex topic. See "man setbuf". It's very important for the stdio streams that if connected to a tty, we match the libc behavior of being line-buffered. So maybe both of these argue for custom stream implementation which wraps the FILE * rather than the raw descriptors. The downside with that is we'd have to jump through the same hoops GUnix{Input,Output}Stream do to implement GPollableOutputStream. It's possible to share code though. I think you're definitely right about separate classes. But how would the user determine whether or not special "console" methods were available? Would we just have GOutputStream * g_stdout_stream_get(void); and they'd have to do: if (G_IS_CONSOLE_OUTPUT_STREAM (out)) pretty_status_line ((GConsoleOutputStream*)out); else g_output_stream_write (out, "Working..."); ?
(In reply to comment #9) > Buffering is a complex topic. See "man setbuf". It's very important for the > stdio streams that if connected to a tty, we match the libc behavior of being > line-buffered. Actually, I think the "fully buffered" mode was a bad design decision in C, because it means that programs behave differently when you redirect their output to a file. (Eg, the program may crash with some logging output still unflushed. Or if you redirect both stdout and stderr, they'll be interleaved incorrectly.) I think we should always default to line-buffered regardless of isatty(). > But how would the user > determine whether or not special "console" methods were available? Would we > just have > > GOutputStream * g_stdout_stream_get(void); > > and they'd have to do: > > if (G_IS_CONSOLE_OUTPUT_STREAM (out)) > pretty_status_line ((GConsoleOutputStream*)out); i was imagining that g_stdout_stream_get() would always return a "GStdoutStream", and you could call g_stdout_stream_is_console() to see if it was attached to a console or not. (Or maybe "GStandardOutputStream"... although I guess the stdout and stderr streams would probably be the same GType, so you wouldn't want a name that too strongly implied it was only stdout... Or we could have GStandardErrorStream as a no-op subclass of GStandardOutputStream...)
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/glib/issues/232.