Skip to content

[libc] Acquire the lock for scanf files #67357

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

Merged
merged 1 commit into from
Sep 25, 2023

Conversation

michaelrj-google
Copy link
Contributor

When creating the new scanf reader design, I forgot to add back the
calls to flockfile and funlockfile in vfscanf_internal. This patch fixes
that, and also changes the system file version to use the normal
variants since ungetc_unlocked isn't always available.

When creating the new scanf reader design, I forgot to add back the
calls to flockfile and funlockfile in vfscanf_internal. This patch fixes
that, and also changes the system file version to use the normal
variants since ungetc_unlocked isn't always available.
@michaelrj-google michaelrj-google requested review from jhuber6 and a team September 25, 2023 18:29
@llvmbot llvmbot added the libc label Sep 25, 2023
@llvmbot
Copy link
Member

llvmbot commented Sep 25, 2023

@llvm/pr-subscribers-libc

Changes

When creating the new scanf reader design, I forgot to add back the
calls to flockfile and funlockfile in vfscanf_internal. This patch fixes
that, and also changes the system file version to use the normal
variants since ungetc_unlocked isn't always available.


Full diff: https://github.com/llvm/llvm-project/pull/67357.diff

1 Files Affected:

  • (modified) libc/src/stdio/scanf_core/vfscanf_internal.h (+19-3)
diff --git a/libc/src/stdio/scanf_core/vfscanf_internal.h b/libc/src/stdio/scanf_core/vfscanf_internal.h
index 68d03d02663b970..715d31ab13eb075 100644
--- a/libc/src/stdio/scanf_core/vfscanf_internal.h
+++ b/libc/src/stdio/scanf_core/vfscanf_internal.h
@@ -22,6 +22,14 @@ namespace internal {
 
 #ifndef LIBC_COPT_STDIO_USE_SYSTEM_FILE
 
+LIBC_INLINE void flockfile(FILE *f) {
+  reinterpret_cast<__llvm_libc::File *>(f)->lock();
+}
+
+LIBC_INLINE void funlockfile(FILE *f) {
+  reinterpret_cast<__llvm_libc::File *>(f)->unlock();
+}
+
 LIBC_INLINE int getc(void *f) {
   unsigned char c;
   auto result = reinterpret_cast<__llvm_libc::File *>(f)->read_unlocked(&c, 1);
@@ -33,7 +41,7 @@ LIBC_INLINE int getc(void *f) {
 }
 
 LIBC_INLINE void ungetc(int c, void *f) {
-  reinterpret_cast<__llvm_libc::File *>(f)->ungetc(c);
+  reinterpret_cast<__llvm_libc::File *>(f)->ungetc_unlocked(c);
 }
 
 LIBC_INLINE int ferror_unlocked(FILE *f) {
@@ -42,13 +50,19 @@ LIBC_INLINE int ferror_unlocked(FILE *f) {
 
 #else // defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE)
 
+// Since ungetc_unlocked isn't always available, we don't acquire the lock for
+// system files.
+LIBC_INLINE void flockfile(::FILE *) { return; }
+
+LIBC_INLINE void funlockfile(::FILE *) { return; }
+
 LIBC_INLINE int getc(void *f) { return ::getc(reinterpret_cast<::FILE *>(f)); }
 
 LIBC_INLINE void ungetc(int c, void *f) {
   ::ungetc(c, reinterpret_cast<::FILE *>(f));
 }
 
-LIBC_INLINE int ferror_unlocked(::FILE *f) { return ::ferror_unlocked(f); }
+LIBC_INLINE int ferror_unlocked(::FILE *f) { return ::ferror(f); }
 
 #endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE
 
@@ -59,10 +73,12 @@ namespace scanf_core {
 LIBC_INLINE int vfscanf_internal(::FILE *__restrict stream,
                                  const char *__restrict format,
                                  internal::ArgList &args) {
+  internal::flockfile(stream);
   scanf_core::Reader reader(stream, &internal::getc, internal::ungetc);
   int retval = scanf_core::scanf_main(&reader, format, args);
   if (retval == 0 && internal::ferror_unlocked(stream))
-    return EOF;
+    retval = EOF;
+  internal::funlockfile(stream);
 
   return retval;
 }

Copy link
Contributor

@jhuber6 jhuber6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG. I'm guessing there's not a good way to check if ungetc_unlocked is available. The GPU case will probably be ismilar to USE_SYSTEM_FILE so I'm assuming that won't cause any issues.

@michaelrj-google
Copy link
Contributor Author

I decided to avoid adding complexity by checking if ungetc_unlocked is available. It isn't available on either of the systems I usually use to test, so I wasn't sure how I'd test it.

@michaelrj-google michaelrj-google merged commit 23552fe into llvm:main Sep 25, 2023
@michaelrj-google michaelrj-google deleted the libcScanfLockFiles branch November 1, 2023 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants