Merge "Document the set*id functions."
diff --git a/libc/Android.bp b/libc/Android.bp
index 61d00cd..fe65ace 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1456,6 +1456,7 @@
         "bionic/pthread_mutex.cpp",
         "bionic/pthread_once.cpp",
         "bionic/pthread_rwlock.cpp",
+        "bionic/pthread_sigqueue.cpp",
         "bionic/pthread_self.cpp",
         "bionic/pthread_setname_np.cpp",
         "bionic/pthread_setschedparam.cpp",
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index 0f17184..ad1ddee 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -176,12 +176,20 @@
     return;
   }
 
+  struct {
+    size_t size;
+    char buf[512];
+  } abort_message;
+
   va_list va;
   va_start(va, fmt);
   if (error_level == ANDROID_FDSAN_ERROR_LEVEL_FATAL) {
     async_safe_fatal_va_list("fdsan", fmt, va);
   } else {
     async_safe_format_log_va_list(ANDROID_LOG_ERROR, "fdsan", fmt, va);
+    size_t len =
+        async_safe_format_buffer_va_list(abort_message.buf, sizeof(abort_message.buf), fmt, va);
+    abort_message.size = len + sizeof(size_t);
   }
   va_end(va);
 
@@ -192,7 +200,9 @@
       __BIONIC_FALLTHROUGH;
     case ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS:
       // DEBUGGER_SIGNAL
-      raise(__SIGRTMIN + 3);
+      sigval abort_msg;
+      abort_msg.sival_ptr = &abort_message;
+      pthread_sigqueue(pthread_self(), __SIGRTMIN + 3, abort_msg);
       break;
 
     case ANDROID_FDSAN_ERROR_LEVEL_FATAL:
@@ -218,7 +228,7 @@
   return result;
 }
 
-static const char* __tag_to_type(uint64_t tag) {
+const char* android_fdsan_get_tag_type(uint64_t tag) {
   uint64_t type = tag >> 56;
   switch (type) {
     case ANDROID_FDSAN_OWNER_TYPE_FILE:
@@ -235,6 +245,8 @@
       return "RandomAccessFile";
     case ANDROID_FDSAN_OWNER_TYPE_PARCELFILEDESCRIPTOR:
       return "ParcelFileDescriptor";
+    case ANDROID_FDSAN_OWNER_TYPE_SQLITE:
+      return "sqlite";
 
     case ANDROID_FDSAN_OWNER_TYPE_GENERIC_00:
     default:
@@ -251,7 +263,7 @@
   }
 }
 
-static uint64_t __tag_to_owner(uint64_t tag) {
+uint64_t android_fdsan_get_tag_value(uint64_t tag) {
   // Lop off the most significant byte and sign extend.
   return static_cast<uint64_t>(static_cast<int64_t>(tag << 8) >> 8);
 }
@@ -264,10 +276,10 @@
 
   uint64_t tag = expected_tag;
   if (!atomic_compare_exchange_strong(&fde->close_tag, &tag, 0)) {
-    const char* expected_type = __tag_to_type(expected_tag);
-    uint64_t expected_owner = __tag_to_owner(expected_tag);
-    const char* actual_type = __tag_to_type(tag);
-    uint64_t actual_owner = __tag_to_owner(tag);
+    const char* expected_type = android_fdsan_get_tag_type(expected_tag);
+    uint64_t expected_owner = android_fdsan_get_tag_value(expected_tag);
+    const char* actual_type = android_fdsan_get_tag_type(tag);
+    uint64_t actual_owner = android_fdsan_get_tag_value(tag);
     if (expected_tag && tag) {
       fdsan_error(
           "attempted to close file descriptor %d, "
@@ -297,6 +309,14 @@
   return rc;
 }
 
+uint64_t android_fdsan_get_owner_tag(int fd) {
+  FdEntry* fde = GetFdEntry(fd);
+  if (!fde) {
+    return 0;
+  }
+  return fde->close_tag;
+}
+
 void android_fdsan_exchange_owner_tag(int fd, uint64_t expected_tag, uint64_t new_tag) {
   FdEntry* fde = GetFdEntry(fd);
   if (!fde) {
@@ -309,18 +329,18 @@
       fdsan_error(
           "failed to exchange ownership of file descriptor: fd %d is "
           "owned by %s 0x%" PRIx64 ", was expected to be owned by %s 0x%" PRIx64,
-          fd, __tag_to_type(tag), __tag_to_owner(tag), __tag_to_type(expected_tag),
-          __tag_to_owner(expected_tag));
+          fd, android_fdsan_get_tag_type(tag), android_fdsan_get_tag_value(tag),
+          android_fdsan_get_tag_type(expected_tag), android_fdsan_get_tag_value(expected_tag));
     } else if (expected_tag && !tag) {
       fdsan_error(
           "failed to exchange ownership of file descriptor: fd %d is "
           "unowned, was expected to be owned by %s 0x%" PRIx64,
-          fd, __tag_to_type(expected_tag), __tag_to_owner(expected_tag));
+          fd, android_fdsan_get_tag_type(expected_tag), android_fdsan_get_tag_value(expected_tag));
     } else if (!expected_tag && tag) {
       fdsan_error(
           "failed to exchange ownership of file descriptor: fd %d is "
           "owned by %s 0x%" PRIx64 ", was expected to be unowned",
-          fd, __tag_to_type(tag), __tag_to_owner(tag));
+          fd, android_fdsan_get_tag_type(tag), android_fdsan_get_tag_value(tag));
     } else if (!expected_tag && !tag) {
       // This should never happen: our CAS failed, but expected == actual?
       async_safe_fatal(
diff --git a/libc/bionic/pthread_sigqueue.cpp b/libc/bionic/pthread_sigqueue.cpp
new file mode 100644
index 0000000..34bda38
--- /dev/null
+++ b/libc/bionic/pthread_sigqueue.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "private/ErrnoRestorer.h"
+#include "pthread_internal.h"
+
+int pthread_sigqueue(pthread_t t, int sig, const union sigval value) {
+  ErrnoRestorer errno_restorer;
+
+  pid_t tid = pthread_gettid_np(t);
+  if (tid == -1) return ESRCH;
+
+  siginfo_t siginfo;
+  siginfo.si_code = SI_QUEUE;
+  siginfo.si_pid = getpid();
+  siginfo.si_uid = getuid();
+  siginfo.si_value = value;
+
+  return syscall(__NR_rt_tgsigqueueinfo, getpid(), tid, sig, &siginfo) ? errno : 0;
+}
diff --git a/libc/include/android/fdsan.h b/libc/include/android/fdsan.h
index 2aa29e3..cbea460 100644
--- a/libc/include/android/fdsan.h
+++ b/libc/include/android/fdsan.h
@@ -97,17 +97,20 @@
   /* android::base::unique_fd */
   ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD = 3,
 
+  /* sqlite-owned file descriptors */
+  ANDROID_FDSAN_OWNER_TYPE_SQLITE = 4,
+
   /* java.io.FileInputStream */
-  ANDROID_FDSAN_OWNER_TYPE_FILEINPUTSTREAM = 251,
+  ANDROID_FDSAN_OWNER_TYPE_FILEINPUTSTREAM = 5,
 
   /* java.io.FileOutputStream */
-  ANDROID_FDSAN_OWNER_TYPE_FILEOUTPUTSTREAM = 252,
+  ANDROID_FDSAN_OWNER_TYPE_FILEOUTPUTSTREAM = 6,
 
   /* java.io.RandomAccessFile */
-  ANDROID_FDSAN_OWNER_TYPE_RANDOMACCESSFILE = 253,
+  ANDROID_FDSAN_OWNER_TYPE_RANDOMACCESSFILE = 7,
 
   /* android.os.ParcelFileDescriptor */
-  ANDROID_FDSAN_OWNER_TYPE_PARCELFILEDESCRIPTOR = 254,
+  ANDROID_FDSAN_OWNER_TYPE_PARCELFILEDESCRIPTOR = 8,
 };
 
 /*
@@ -129,6 +132,25 @@
  */
 int android_fdsan_close_with_tag(int fd, uint64_t tag) __INTRODUCED_IN_FUTURE __attribute__((__weak__));
 
+/*
+ * Get a file descriptor's current owner tag.
+ *
+ * Returns 0 for untagged and invalid file descriptors.
+ */
+uint64_t android_fdsan_get_owner_tag(int fd);
+
+/*
+ * Get an owner tag's string representation.
+ *
+ * The return value points to memory with static lifetime, do not attempt to modify it.
+ */
+const char* android_fdsan_get_tag_type(uint64_t tag);
+
+/*
+ * Get an owner tag's value, with the type masked off.
+ */
+uint64_t android_fdsan_get_tag_value(uint64_t tag);
+
 enum android_fdsan_error_level {
   // No errors.
   ANDROID_FDSAN_ERROR_LEVEL_DISABLED,
diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h
index 4e1a185..cab1156 100644
--- a/libc/include/android/versioning.h
+++ b/libc/include/android/versioning.h
@@ -17,15 +17,15 @@
 #ifndef ANDROID_VERSIONING_H
 #define ANDROID_VERSIONING_H
 
-#define __INTRODUCED_IN(api_level) __attribute__((annotate("introduced_in=" #api_level)))
+#define __INTRODUCED_IN(api_level) __attribute__((annotate("introduced_in=" __STRING(api_level))))
 #define __INTRODUCED_IN_FUTURE __attribute__((annotate("introduced_in_future")))
-#define __DEPRECATED_IN(api_level) __attribute__((annotate("deprecated_in=" #api_level)))
-#define __REMOVED_IN(api_level) __attribute__((annotate("obsoleted_in=" #api_level)))
-#define __INTRODUCED_IN_32(api_level) __attribute__((annotate("introduced_in_32=" #api_level)))
-#define __INTRODUCED_IN_64(api_level) __attribute__((annotate("introduced_in_64=" #api_level)))
-#define __INTRODUCED_IN_ARM(api_level) __attribute__((annotate("introduced_in_arm=" #api_level)))
-#define __INTRODUCED_IN_X86(api_level) __attribute__((annotate("introduced_in_x86=" #api_level)))
-#define __INTRODUCED_IN_MIPS(api_level) __attribute__((annotate("introduced_in_mips=" #api_level)))
+#define __DEPRECATED_IN(api_level) __attribute__((annotate("deprecated_in=" __STRING(api_level))))
+#define __REMOVED_IN(api_level) __attribute__((annotate("obsoleted_in=" __STRING(api_level))))
+#define __INTRODUCED_IN_32(api_level) __attribute__((annotate("introduced_in_32=" __STRING(api_level))))
+#define __INTRODUCED_IN_64(api_level) __attribute__((annotate("introduced_in_64=" __STRING(api_level))))
+#define __INTRODUCED_IN_ARM(api_level) __attribute__((annotate("introduced_in_arm=" __STRING(api_level))))
+#define __INTRODUCED_IN_X86(api_level) __attribute__((annotate("introduced_in_x86=" __STRING(api_level))))
+#define __INTRODUCED_IN_MIPS(api_level) __attribute__((annotate("introduced_in_mips=" __STRING(api_level))))
 
 #define __VERSIONER_NO_GUARD __attribute__((annotate("versioner_no_guard")))
 
diff --git a/libc/include/poll.h b/libc/include/poll.h
index 13b7385..e3a9039 100644
--- a/libc/include/poll.h
+++ b/libc/include/poll.h
@@ -49,7 +49,7 @@
  * Returns the number of ready file descriptors on success, 0 for timeout,
  * and returns -1 and sets `errno` on failure.
  */
-int poll(struct pollfd* _Nonnull __fds, nfds_t __count, int __timeout_ms);
+int poll(struct pollfd* _Nullable __fds, nfds_t __count, int __timeout_ms);
 
 /**
  * [ppoll(3)](http://man7.org/linux/man-pages/man3/ppoll.3.html) waits on a set of file descriptors
@@ -61,12 +61,12 @@
  *
  * Available since API level 28.
  */
-int ppoll(struct pollfd* _Nonnull __fds, nfds_t __count, const struct timespec* _Nullable __timeout, const sigset_t* _Nullable __mask) __INTRODUCED_IN(21);
+int ppoll(struct pollfd* _Nullable __fds, nfds_t __count, const struct timespec* _Nullable __timeout, const sigset_t* _Nullable __mask) __INTRODUCED_IN(21);
 
 /**
  * Like ppoll() but allows setting a signal mask with RT signals even from a 32-bit process.
  */
-int ppoll64(struct pollfd* _Nonnull __fds, nfds_t __count, const struct timespec* _Nullable __timeout, const sigset64_t* _Nullable __mask) __INTRODUCED_IN(28);
+int ppoll64(struct pollfd* _Nullable  __fds, nfds_t __count, const struct timespec* _Nullable __timeout, const sigset64_t* _Nullable __mask) __INTRODUCED_IN(28);
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
 #define _POLL_H_
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 00860d5..9d1030a 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -113,6 +113,10 @@
 void psignal(int __signal, const char* __msg) __INTRODUCED_IN(17);
 
 int pthread_kill(pthread_t __pthread, int __signal);
+#if defined(__USE_GNU)
+int pthread_sigqueue(pthread_t __pthread, int __signal, const union sigval __value) __INTRODUCED_IN(__ANDROID_API_Q__);
+#endif
+
 int pthread_sigmask(int __how, const sigset_t* __new_set, sigset_t* __old_set);
 int pthread_sigmask64(int __how, const sigset64_t* __new_set, sigset64_t* __old_set) __INTRODUCED_IN(28);
 
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 13ad4fe..26a05c8 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -38,7 +38,6 @@
 #define	_SYS_CDEFS_H_
 
 #include <android/api-level.h>
-#include <android/versioning.h>
 
 #define __BIONIC__ 1
 
@@ -92,7 +91,6 @@
 #define	___STRING(x)	__STRING(x)
 #define	___CONCAT(x,y)	__CONCAT(x,y)
 
-#if defined(__STDC__) || defined(__cplusplus)
 #define	__P(protos)	protos		/* full-blown ANSI C */
 #define	__CONCAT1(x,y)	x ## y
 #define	__CONCAT(x,y)	__CONCAT1(x,y)
@@ -102,12 +100,9 @@
 #define	__inline	inline		/* convert to C++ keyword */
 #endif /* !__cplusplus */
 
-#else	/* !(__STDC__ || __cplusplus) */
-#define	__P(protos)	()		/* traditional C preprocessor */
-#define	__CONCAT(x,y)	x/**/y
-#define	__STRING(x)	"x"
+#include <android/versioning.h>
 
-#endif	/* !(__STDC__ || __cplusplus) */
+#include <android/versioning.h>
 
 #define __always_inline __attribute__((__always_inline__))
 #define __attribute_const__ __attribute__((__const__))
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index bbde88b..e54dd65 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -288,6 +288,7 @@
 #define SOL_ALG 279
 #define SOL_NFC 280
 #define SOL_KCM 281
+#define SOL_TLS 282
 
 #define IPX_TYPE 1
 
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 6d39812..8fb07f7 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1426,8 +1426,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 1cf48b1..8c5eb89 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1347,8 +1347,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 135206e..c5f0910 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1451,8 +1451,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index a330a45..fbaf508 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1410,8 +1410,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 1cf48b1..8c5eb89 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1347,8 +1347,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 7a2fe9a..db86e55 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1408,8 +1408,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 1cf48b1..8c5eb89 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1347,8 +1347,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index cc95ef7..52a097b 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -597,6 +597,42 @@
   ASSERT_EQ(1, g_sigqueue_signal_handler_call_count);
 }
 
+TEST(signal, pthread_sigqueue_self) {
+  ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler, SA_SIGINFO);
+  sigval_t sigval;
+  sigval.sival_int = 1;
+  errno = 0;
+  ASSERT_EQ(0, pthread_sigqueue(pthread_self(), SIGALRM, sigval));
+  ASSERT_EQ(0, errno);
+  ASSERT_EQ(1, g_sigqueue_signal_handler_call_count);
+}
+
+TEST(signal, pthread_sigqueue_other) {
+  ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler, SA_SIGINFO);
+  sigval_t sigval;
+  sigval.sival_int = 1;
+
+  sigset_t mask;
+  sigfillset(&mask);
+  pthread_sigmask(SIG_SETMASK, &mask, nullptr);
+  pthread_t thread;
+  int rc = pthread_create(&thread, nullptr,
+                          [](void*) -> void* {
+                            sigset_t mask;
+                            sigemptyset(&mask);
+                            sigsuspend(&mask);
+                            return nullptr;
+                          },
+                          nullptr);
+  ASSERT_EQ(0, rc);
+
+  errno = 0;
+  ASSERT_EQ(0, pthread_sigqueue(thread, SIGALRM, sigval));
+  ASSERT_EQ(0, errno);
+  pthread_join(thread, nullptr);
+  ASSERT_EQ(1, g_sigqueue_signal_handler_call_count);
+}
+
 TEST(signal, sigwaitinfo) {
   SignalMaskRestorer smr;