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
Improve portability for POSIX systems #99
Conversation
We use simple CGO style functions for the low level accesses to set or get termios attributes and the TIOCGWINSIZE ioctl. This helps for systems where SYS_ioctl may be absent (such as solaris), while stil keeping POSIX compatibility. (Note however that the TIOCGWINSIZE call may be missing on some systems. In such a case we provide a default guess of 80x24, unless environment variables COLUMNS and LINES indicate otherwise.) Additionally, there is no need for non-blocking I/O. With Go, we can use os.Read() in a goroutine, and it will return as soon as data is available, even if the buffer is not open. This helps with both portability (O_ASYNC and F_SETOWN aren't universally available), and readability. Btw, these changes also allow us to eliminate the use of the unsafe pointers in the Go code. I've tested the included demo programs, as well as my own program on both Darwin and illumos/solaris systems. Furthermore, I've tested the topsl (github.com/gdamore/topsl) demos with these changes on both systems. Note that on solaris this requires the use of go v1.5 or better, as cgo is not present on older versions of that port. All POSIX platforms supported by Go 1.5 also support cgo.
I think https://github.com/gdamore/termbox-go/blob/a534321a31d4f8ea882d7fcee89c5f0244eb152d/api.go#L93 diff --git a/api.go b/api.go
index dd2423a..41f7494 100644
--- a/api.go
+++ b/api.go
@@ -90,7 +90,7 @@ func Interrupt() {
// Finalizes termbox library, should be called after successful initialization
// when termbox's functionality isn't required anymore.
func Close() {
- quit <- 1
+ close(quit)
out.WriteString(funcs[t_show_cursor])
out.WriteString(funcs[t_sgr0])
out.WriteString(funcs[t_clear_screen]) |
If only go had proper build tags support, we could add it as a build variant for systems where provided syscall-based implementations don't work. But at the moment, since syscalls actually cover most of the systems, I would rather prefer having them. So, I don't know when I'll be able to solve your illumos/Solaris portability problem. Frankly, I want to get rid of SIGIO, but we still need to keep this ability to break the blocking read call. It's possible to implement that via |
Oh, and about the lack of ioctl, how terminals work there then? I mean libc should implement it somehow, if not via ioctl, then how all the tcsetattr stuff works? |
What platforms do this? I've never heard of any POSIX platform where this is true.
I share the sentiment of minimalism. However your solution doesn't avoid the problem really but just moves it. There aren't any platforms where cgo is unavailable (this is new since go 1.5) and my approach creates no additional runtime dependencies apart from libc. I'm now recalling that go doesn't link against libc on Linux. But on Solaris it does.
That leaves it unusable for me and my platform. :-(
In Solaris the system call interface is not a public interface. Instead developers are supposed to call the c library.
|
We have ioctl in Solaris. Just not in the go port. However the termios functions are implemented in the C library on top of ioctl. This is the same for pretty much all platforms. Sent from my iPhone
|
Could be darwin (aka MacOSX). I'm not saying that I don't want to make termbox-go as portable as possible, I'm just saying that I don't want to go with cgo paths on all platforms.The fact that cgo is always available is not an issue. The issue is portability across different glibc versions. Or the lack of glibc as a dependency. Maybe it's not a big deal, but I'd like to keep things that way. I think we can even do that without special build tags. Let's just make a build which uses cgo on solaris and doesn't use it on all other platforms. But what about SIGIO? Is it unavailable there? |
No Darwin behaves normally. I tested this very specifically there.
Nope. Darwin works just like you'd expect. If you close a file descriptor outstanding reads will return EBADF. Btw it would be a tragic bug for any platform to NOT do that. I think there is a fair body of software that may depend on this behavior. What close can do is wait for inflight writes to complete or fail depending on where they are in the process. My guess is that in the upper part of the stack they would just fail but once the write has been scheduled by buffer cache layer that the close will wait until that completes if the file is marked synchronous. (None of which matters for us. We don't use O_SYNC files. That's for databases and such.)
Yeah I think I understand. Perhaps we can offer a different approach using cgo with my approach for platforms like illumos. Frankly the go folks need to add these low level functions to their base code if they really believe that avoiding libc is a goal. It's crazy that application developers have to get involved with the kernel system call interface - that should always be abstracted away behind a language call interface. We believe this so strongly with solaris that we've long ago stopped shipping static libc. (This caused some challenges in porting go to Solaris.) The system calls can change without notice in Solaris systems because we only promise a stable c calling interface and we change libc and the kernel in lockstep.
SIGIO is available. But utterly unnecessary. I remain adamant that this approach is flat out wrong. And building select or poll syscalls into go app code is probably extraordinarily problematic as this is one area where I think the various operating systems have a great deal of difference in their system call interfaces. (All hidden by standardizes C library interfaces of course.)
|
Agreed. Sent from my iPhone
|
Read the comment in the commit. Are you sure about the fact that it works just fine on darwin? I'm not just making this up. Although, will test it myself anyway. |
So I did some more research. Apparently when using cgo, the C library is Since libc must be on the system in order for the system to function at To be clear, I completely understand and agree with the intent to avoid On Tue, Sep 22, 2015 at 8:16 AM, Garrett D'Amore garrett@damore.org wrote:
|
I wrote another test program, which I can attach. It turns out that Darwin However there is a very nice workaround that avoids the whole SIGIO The test program is below. Without the tcflush() the programs works
On Tue, Sep 22, 2015 at 9:04 AM, Garrett D'Amore garrett@damore.org wrote:
|
Just replied. You're right... /dev/tty (not files in general) has a On Tue, Sep 22, 2015 at 8:36 AM, nsf notifications@github.com wrote:
|
I'm no longer interested in pursuing this PR, having long long ago spawned the tcell project which does what I need it to (and more). |
We use simple CGO style functions for the low level accesses to
set or get termios attributes and the TIOCGWINSIZE ioctl. This
helps for systems where SYS_ioctl may be absent (such as solaris),
while stil keeping POSIX compatibility. (Note however that the
TIOCGWINSIZE call may be missing on some systems. In such a case
we provide a default guess of 80x24, unless environment variables
COLUMNS and LINES indicate otherwise.)
Additionally, there is no need for non-blocking I/O. With Go,
we can use os.Read() in a goroutine, and it will return as soon
as data is available, even if the buffer is not open. This helps
with both portability (O_ASYNC and F_SETOWN aren't universally
available), and readability.
Btw, these changes also allow us to eliminate the use of the
unsafe pointers in the Go code.
I've tested the included demo programs, as well as my own program
on both Darwin and illumos/solaris systems. Furthermore, I've
tested the topsl (github.com/gdamore/topsl) demos with these
changes on both systems.
Note that on solaris this requires the use of go v1.5 or better,
as cgo is not present on older versions of that port. All POSIX
platforms supported by Go 1.5 also support cgo.