zig icon indicating copy to clipboard operation
zig copied to clipboard

Incorrect MIPS termios constants

Open wooster0 opened this issue 1 year ago • 4 comments

Zig Version

0.10.0-dev.4418+99c3578f6

Steps to Reproduce

#12079 apparently exposed an interesting C ABI issue for MIPS Linux that @topolarity found where when trying to run tests like this the output looks malformed like this:

$ cat test0.zig                                                                               
test { }

test "test a" {
    return error.SkipZigTest;
}

test "test b" {
    return error.SkipZigTest;
}
$ ./build/stage3/bin/zig test test0.zig -target mips-linux --test-cmd qemu-mips --test-cmd-bin
Test [2/3] test.test a... SKIP
                              Test [3/3] test.test b... SKIP
                                                            1 passed; 2 skipped; 0 failed.
                                                                                          %    

The issue boils down to this tcsetattr https://github.com/ziglang/zig/blob/5127dae7a28159af8d348d3680f34d51c5cadaaa/lib/std/Progress.zig#L246 in getTerminalCursorColumn in std.Progress.

This however is purely a C ABI issue. It should actually work.

Here's reproducible code: it gets termios (the terminal's config) and then sets it. It shouldn't change the terminal at all:

Zig:

const std = @import("std");

pub fn main() !void {
    const current_termios = try std.os.tcgetattr(std.os.STDERR_FILENO);
    try std.os.tcsetattr(std.os.STDERR_FILENO, .NOW, current_termios);
}
zig build-exe x.zig -target mips-linux; qemu-mips x

Outcome: broken terminal with echo etc. not working.

C:

#include <termios.h>
#include <unistd.h>

int main() {
    struct termios current_termios;
    tcgetattr(STDERR_FILENO, &current_termios);
    tcsetattr(STDERR_FILENO, TCSANOW, &current_termios);
}
mips-linux-gnu-gcc -static x.c; qemu-mips a.out

Outcome: terminal is the same as before.

You might need the packages gcc-mips-linux-gnu, qemu-user, and qemu-system-mips for your system in order to reproduce this issue.

Expected Behavior

The terminal doesn't break.

wooster0 avatar Oct 16 '22 19:10 wooster0

Oh I thought this was probably a C ABI issue, but it looks like a broken syscall. The layout of termios matches just fine on MIPS and the example works with -lc, so the problem is when Zig performs the ioctl syscall directly

That or there's some kind of initialization dance that libc is doing which Zig is not

topolarity avatar Oct 16 '22 20:10 topolarity

Aha! This is suspicious:

pub const T = struct {
    pub const CGETS = if (is_mips) 0x540D else 0x5401;
    pub const CSETS = 0x5402;
    pub const CSETSW = 0x5403;
    pub const CSETSF = 0x5404;
    pub const CGETA = 0x5405;
    pub const CSETA = 0x5406;
    ....

Indeed almost all of these are incorrect for MIPS, except for CGETS

topolarity avatar Oct 16 '22 20:10 topolarity

Ops, missclick. Sorry about that

Hejsil avatar Oct 16 '22 21:10 Hejsil

See arch/mips/include/uapi/asm/ioctls.h for the full list. Also note the comment in include/uapi/asm-generic/ioctls.h:

The architectures that use different values here typically try to be compatible with some Unix variants for the same architecture.

In this case I bet it's copying IRIX.

The-King-of-Toasters avatar Oct 17 '22 06:10 The-King-of-Toasters

This PR is related: https://github.com/ziglang/zig/pull/12771

It tries to define the constants the same way the kernel does, however, I haven't confirmed if all ioctl numbers behave this way, there could be some older values that don't use this new mechanism.

marler8997 avatar Nov 06 '22 15:11 marler8997