-
Notifications
You must be signed in to change notification settings - Fork 10.9k
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
[libc] Lock the output stream for the 'puts' call #76513
Conversation
@llvm/pr-subscribers-libc Author: Joseph Huber (jhuber6) ChangesSummary: Wasn't sure if this required a test as it would be difficult since Full diff: https://github.com/llvm/llvm-project/pull/76513.diff 1 Files Affected:
diff --git a/libc/src/stdio/generic/puts.cpp b/libc/src/stdio/generic/puts.cpp
index d8d69332566cd0..052977e5620646 100644
--- a/libc/src/stdio/generic/puts.cpp
+++ b/libc/src/stdio/generic/puts.cpp
@@ -15,14 +15,28 @@
namespace LIBC_NAMESPACE {
+// Simple helper to unlock the file once destroyed.
+struct ScopedLock {
+ ScopedLock(LIBC_NAMESPACE::File *stream) : stream(stream) { stream->lock(); }
+ ~ScopedLock() { stream->unlock(); }
+
+private:
+ LIBC_NAMESPACE::File *stream;
+};
+
LLVM_LIBC_FUNCTION(int, puts, (const char *__restrict str)) {
cpp::string_view str_view(str);
+
+ // We need to lock the stream to ensure the newline is always appended.
+ ScopedLock lock(LIBC_NAMESPACE::stdout);
+
auto result = LIBC_NAMESPACE::stdout->write(str, str_view.size());
if (result.has_error())
libc_errno = result.error;
size_t written = result.value;
if (str_view.size() != written) {
// The stream should be in an error state in this case.
+ LIBC_NAMESPACE::stdout->unlock();
return EOF;
}
result = LIBC_NAMESPACE::stdout->write("\n", 1);
|
private: | ||
LIBC_NAMESPACE::File *stream; | ||
}; | ||
|
||
LLVM_LIBC_FUNCTION(int, puts, (const char *__restrict str)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this is marked as __restrict
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think all of the implementations of string functions are like this. My best guess is that it's giving the same effect as const char const *
without changing the signature or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, can you please provide more info on this point; it doesn't sound right to me.
My understanding of __restrict
is that it has to do with strict aliasing of function parameters. If there's only 1 parameter, there is nothing to be concerned with wrt to aliasing.
So why add __restrict here?
ping |
Summary: The `puts` function consists of an initial write and then another write to append the newline. When executing code in parallel, it is possible for these writes to becomes disjointed. This code adds an explicit lock call to ensure that the string is always appended by the newline as the users expects. Wasn't sure if this required a test as it would be difficult since reproducing it would be flaky.
Summary:
The
puts
function consists of an initial write and then another writeto append the newline. When executing code in parallel, it is possible
for these writes to becomes disjointed. This code adds an explicit lock
call to ensure that the string is always appended by the newline as the
users expects.
Wasn't sure if this required a test as it would be difficult since
reproducing it would be flaky.