From 13d0cdb68f839a2c13b739f9fe3ed87ebc86c049 Mon Sep 17 00:00:00 2001
From: Josh Triplett <josh@joshtriplett.org>
Date: Sun, 9 Aug 2020 15:10:20 -0700
Subject: [PATCH] Expose si_pid, si_uid, and si_status from siginfo_t as
 functions

On Linux, siginfo_t cannot expose these fields directly due to
https://github.com/rust-lang/libc/issues/716 , so expose them as
functions, just like si_addr and si_value.

In order to get alignment correct on both 32-bit and 64-bit
architectures, define an sifields union that includes a pointer field,
to ensure that it has the same alignment as a pointer.
---
 src/unix/bsd/apple/mod.rs            |  8 +++++
 src/unix/bsd/freebsdlike/mod.rs      |  8 +++++
 src/unix/haiku/mod.rs                | 14 ++++++++
 src/unix/linux_like/linux/gnu/mod.rs | 49 ++++++++++++++++++++++++++++
 src/vxworks/mod.rs                   | 18 ++++++++++
 5 files changed, 97 insertions(+)

diff --git a/src/unix/bsd/apple/mod.rs b/src/unix/bsd/apple/mod.rs
index f1309747..f56ee02b 100644
--- a/src/unix/bsd/apple/mod.rs
+++ b/src/unix/bsd/apple/mod.rs
@@ -680,6 +680,14 @@ impl siginfo_t {
 
         (*(self as *const siginfo_t as *const siginfo_timer)).si_value
     }
+
+    pub unsafe fn si_pid(&self) -> ::pid_t {
+        self.si_pid
+    }
+
+    pub unsafe fn si_uid(&self) -> ::uid_t {
+        self.si_uid
+    }
 }
 
 cfg_if! {
diff --git a/src/unix/bsd/freebsdlike/mod.rs b/src/unix/bsd/freebsdlike/mod.rs
index b75c1a8e..e9f70579 100644
--- a/src/unix/bsd/freebsdlike/mod.rs
+++ b/src/unix/bsd/freebsdlike/mod.rs
@@ -31,6 +31,14 @@ impl siginfo_t {
     pub unsafe fn si_value(&self) -> ::sigval {
         self.si_value
     }
+
+    pub unsafe fn si_pid(&self) -> ::pid_t {
+        self.si_pid
+    }
+
+    pub unsafe fn si_uid(&self) -> ::uid_t {
+        self.si_uid
+    }
 }
 
 s! {
diff --git a/src/unix/haiku/mod.rs b/src/unix/haiku/mod.rs
index 27f88f15..adcac2e5 100644
--- a/src/unix/haiku/mod.rs
+++ b/src/unix/haiku/mod.rs
@@ -38,6 +38,20 @@ impl ::Clone for timezone {
     }
 }
 
+impl siginfo_t {
+    pub unsafe fn si_addr(&self) -> *mut ::c_void {
+        self.si_addr
+    }
+
+    pub unsafe fn si_pid(&self) -> ::pid_t {
+        self.si_pid
+    }
+
+    pub unsafe fn si_uid(&self) -> ::uid_t {
+        self.si_uid
+    }
+}
+
 s! {
     pub struct in_addr {
         pub s_addr: ::in_addr_t,
diff --git a/src/unix/linux_like/linux/gnu/mod.rs b/src/unix/linux_like/linux/gnu/mod.rs
index 44796c3e..982916a2 100644
--- a/src/unix/linux_like/linux/gnu/mod.rs
+++ b/src/unix/linux_like/linux/gnu/mod.rs
@@ -313,6 +313,55 @@ impl siginfo_t {
     }
 }
 
+cfg_if! {
+    if #[cfg(libc_union)] {
+        // Internal, for casts to access union fields
+        #[repr(C)]
+        #[derive(Copy,Clone)]
+        struct sifields_sigchld {
+            si_pid: ::pid_t,
+            si_uid: ::uid_t,
+            si_status: ::c_int,
+        }
+
+        // Internal, for casts to access union fields
+        #[repr(C)]
+        union sifields {
+            _align_pointer: *mut ::c_void,
+            sigchld: sifields_sigchld,
+        }
+
+        // Internal, for casts to access union fields. Note that some variants
+        // of sifields start with a pointer, which makes the alignment of
+        // sifields vary on 32-bit and 64-bit architectures.
+        #[repr(C)]
+        struct siginfo_f {
+            _si_signo: ::c_int,
+            _si_errno: ::c_int,
+            _si_code: ::c_int,
+            sifields: sifields,
+        }
+
+        impl siginfo_t {
+            unsafe fn sifields(&self) -> &sifields {
+                &(*(self as *const siginfo_t as *const siginfo_f)).sifields
+            }
+
+            pub unsafe fn si_pid(&self) -> ::pid_t {
+                self.sifields().sigchld.si_pid
+            }
+
+            pub unsafe fn si_uid(&self) -> ::uid_t {
+                self.sifields().sigchld.si_uid
+            }
+
+            pub unsafe fn si_status(&self) -> ::c_int {
+                self.sifields().sigchld.si_status
+            }
+        }
+    }
+}
+
 s_no_extra_traits! {
     pub struct utmpx {
         pub ut_type: ::c_short,
diff --git a/src/vxworks/mod.rs b/src/vxworks/mod.rs
index 2ca38d5e..2a3ac7ff 100755
--- a/src/vxworks/mod.rs
+++ b/src/vxworks/mod.rs
@@ -112,6 +112,24 @@ impl ::Clone for _Vx_semaphore {
     }
 }
 
+impl siginfo_t {
+    pub unsafe fn si_addr(&self) -> *mut ::c_void {
+        self.si_addr
+    }
+
+    pub unsafe fn si_value(&self) -> ::sigval {
+        self.si_value
+    }
+
+    pub unsafe fn si_pid(&self) -> ::pid_t {
+        self.si_pid
+    }
+
+    pub unsafe fn si_uid(&self) -> ::uid_t {
+        self.si_uid
+    }
+}
+
 s! {
     // b_pthread_condattr_t.h
     pub struct pthread_condattr_t {
-- 
GitLab