Skip to content
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

feat(Common): use pipe2 and minor fixes #638

Closed
wants to merge 1 commit into from

Conversation

apocelipes
Copy link
Contributor

@apocelipes apocelipes commented Nov 29, 2023

  • Use pipe2 on Linux and BSDs, which can set all flags through a single syscall.
  • macOS/darwin does not support pipe2, add a wrapper for it.
  • Close pipes when fork() failed. These fds should be closed when the function returns.
  • Set O_CLOEXEC at pipes, the exec() family of functions will close this fds automatically.
  • Use _exit instead of exit. Exit calls the callbacks registered by atexit and flushes the stdio's buffer, which can lead to some unexpected behavior, especially after an exec syscall failure.
  • Setting O_NONBLOCK at pipes won't be a problem. The pipe has 64k(Linux) or 16k(BSDs/macOS) default buffer, which is large enough and could not cause an EAGAIN error in fastfetch's use-cases.

- Use pipe2 on Linux and BSDs, which can set all flags through a single syscall.
- macOS/darwin does not support pipe2, add a wrapper for it.
- Close pipes when fork() failed. These fds should be closed when
  the function returns.
- Set O_CLOEXEC at pipes, the exec() family of functions will close
  this fds automatically.
- Use _exit instead of exit. Exit calls the callbacks registered by atexit
  and flushes the stdio's buffer, which can lead to some unexpected behavior,
  especially after an exec syscall failure.
- Set O_NONBLOCK at pipes won't be a problem. The pipe has 64k(Linux) or
  16k(BSDs/macOS) default buffer, which is large enough and could not cause
  an EAGAIN error in fastfetch's usecases.
@CarterLi
Copy link
Member

CarterLi commented Nov 29, 2023

Setting O_NONBLOCK at pipes won't be a problem. The pipe has 64k(Linux) or 16k(BSDs/macOS) default buffer, which is large enough and could not cause an EAGAIN error in fastfetch's use-cases.

We have a use case which prints more than 100 KiB texts

shennong:/data/local/tmp $ /system/bin/dumpsys display > test.txt
shennong:/data/local/tmp $ ls -lh
total 132K
-rw-rw-rw- 1 shell shell 129K 2023-11-29 20:26 test.txt
shennong:/data/local/tmp $

Foreign processes are something you cannot control. Let's not assume that.

@apocelipes
Copy link
Contributor Author

Foreign processes are something you cannot control. Let's not assume that.

Well, exceeding 64k does not necessarily cause an EAGAIN, but it does increase the probability that the called program will encounter an EAGAIN. The standard library already handles this situation correctly for programs that use stdio to print data to standard output/error. The only programs that really need to worry about are those that write directly to the standard output using system calls such as write, and at least not in the programs that fastfetch currently calls.

@CarterLi
Copy link
Member

CarterLi commented Nov 29, 2023

You make your program less stable for what, two less fcntl syscalls?

And I am a major macOS user, you have it 2 more syscalls for no reason.

I won't merge this. That's all.

@apocelipes
Copy link
Contributor Author

You make your program less stable for what, two less fcntl syscalls?

And I am a major macOS user, you have it 2 more syscalls for no reason.

I won't merge this. That's all.

The same problem exists in the origin code. fcntl will change the state of the fd.

@apocelipes
Copy link
Contributor Author

apocelipes commented Nov 29, 2023

And I am a major macOS user, you have it 2 more syscalls for no reason.

There is also two close syscall be reduced, not too bad, isn't it? Actually, if timeout is set, 3 syscall will be reduced

@apocelipes
Copy link
Contributor Author

apocelipes commented Nov 29, 2023

Honestly non-blocking is not necessary here either, pipe only blocks read when it doesn't have any data in its buffer.
The correct way to do timeout is not to use non-blocking io, but to use a big enough buff (as big as the buffer inside the pipe) to call poll again no matter how much data is read.

Also, O_CLOEXEC is necessary, PEP 433 has told u why. The major reason is security.

This will be another issue, i would like to open a new issue and work on it.

@apocelipes
Copy link
Contributor Author

I'll close this, another PR would fix all abrove issues.

@apocelipes apocelipes closed this Nov 29, 2023
@apocelipes apocelipes deleted the feat-pipe2 branch November 30, 2023 04:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants