Why is _exit (0) (exiting syscall) not allowing me to get any stdout file?

I have a GAS build program for Linux x86-32 ending with the following:

movl $1, %eax movl $0, %ebx # argument for _exit int $0x80 

When I exit like this, the program works fine, but if I try to read the output of stdout, I get nothing (using less or wc).

I tried compiling a minimal C program and comparing strace outputs. The only difference I found was that GCC made the C program ( int main() { printf("donkey\n"); } ) an implicit exit with exit_group(0) in the output of strace.

I tried changing my ASM program to exit with call exit instead of raw syscall. The standard version is now read as usual.

Test case

 .data douout: .string "monkey\n" .text .globl main main: pushl $douout call printf # Exit movl $1, %eax movl $0, %ebx int $0x80 

Compile and run:

 $ yasm -g dwarf2 -f elf -p gas t.asm && gcc -g -melf_i386 -ot to && ./t | wc -c 0 

Expected:

 7 

EDIT:

I tried calling both tcflush and fflush and I still have a problem. With fflush I even get segfault.

 0xb7e9e7c9 in _IO_fflush (fp=0x804a018) at iofflush.c:42 42 iofflush.c: No such file or directory. in iofflush.c (gdb) bt #0 0xb7e9e7c9 in _IO_fflush (fp=0x804a018) at iofflush.c:42 #1 0x08048434 in main () at t.asm:12 (gdb) frame 1 #1 0x08048434 in main () at t.asm:12 12 call fflush (gdb) list 7 8 pushl $douout 9 call printf 10 # Exit 11 movl $0, %eax 12 call fflush 13 movl $1, %eax 14 movl $0, %ebx 15 int $0x80 

EDIT2:

OK, now everything works. I used the wrong calling convention that I copied here: Printf without a newline in the assembly

The argument for fflush should be on the stack as usual.

 $ cat t.asm .data douout: .string "monkey\n" .text .globl main main: pushl $douout call printf # Exit pushl $0 call fflush movl $1, %eax movl $0, %ebx int $0x80 $ yasm -g dwarf2 -f elf -p gas t.asm && gcc -g -melf_i386 -ot to && ./t | wc -c 7 $ 

Thanks to everyone, especially nos.

+3
source share
3 answers

when you connect stdout to wc, stdout becomes fully buffered.

_exit immediately terminates the process and does not start atexit () and other cleanup handlers. Runtimes will register handlers that will run when exiting, which flushes the open * file, such as stdout. When these handlers are not executed on exit, buffered data will be lost.

You should see the output if you call fflush(stdout) after calling printf, or if you just run the program in the console without passing the output to another program - in this case, stdout will usually be buffered by line, so stdout is cleared whenever you write \ n

+1
source

The output sent in the standard way is usually buffered. If you call fflush(stdout) before calling _exit , you should get your result.

The reason exit is because this function guarantees closing and clearing any open threads (for example, stdout) before calling _exit to actually terminate the program.

+1
source

According to the manual page for _exit(2)

Whether it flushes standard I / O buffers and deletes temporary files created using tmpfile (3) depends on the implementation. On the other hand, _exit () closes the open file descriptors, and this may result in an unknown delay waiting for the output to complete. If a delay is undesirable, it may be useful to call functions like tcflush (3) before calling _exit (). Regardless of whether any pending I / O is canceled, and which pending I / O can be canceled by _exit (), depends on the implementation.

So, if you did not reset stdout, it can be discarded.

+1
source

Source: https://habr.com/ru/post/903752/


All Articles