folly/subprocess: fix one -Wsign-conversion and clag 3.9 test
authorIgor Sugak <sugak@fb.com>
Tue, 15 Mar 2016 20:00:36 +0000 (13:00 -0700)
committerFacebook Github Bot 4 <facebook-github-bot-4-bot@fb.com>
Tue, 15 Mar 2016 20:05:22 +0000 (13:05 -0700)
Summary:easy:
`options.parentDeathSignal_` is `int`, and second argument of `prctl` is `unsigned long`. Adding explicit cast.

hard:
this change is fixing a real problem when building folly with Clang 3.9.0. The [[ https://github.com/llvm-mirror/clang/commit/f4ddf94ecbd9899a497151621f3871545e24e93b | new alignment implementation ]] in `-O3` generates code that breaks folly's `ParentDeathSubprocessTest.ParentDeathSignal`.
For the following snipped of code:
```lang=cpp
  if (options.parentDeathSignal_ != 0) {
    if (prctl(PR_SET_PDEATHSIG, options.parentDeathSignal_, 0, 0, 0) == -1) {
      return errno;
    }
  }
```
LLVM generates the following assembly:
```lang=asm
   0x000000000040a77b <+347>:   mov    0x28(%r14),%rsi
   0x000000000040a77f <+351>:   test   %esi,%esi
   0x000000000040a781 <+353>:   je     0x40a7a1 <folly::Subprocess::prepareChild(folly::Subprocess::Options const&, __sigset_t const*, char const*) const+385>
   0x000000000040a783 <+355>:   mov    $0x1,%edi
   0x000000000040a788 <+360>:   xor    %edx,%edx
   0x000000000040a78a <+362>:   xor    %ecx,%ecx
   0x000000000040a78c <+364>:   xor    %r8d,%r8d
   0x000000000040a78f <+367>:   xor    %eax,%eax
   0x000000000040a791 <+369>:   callq  0x405ad0 <prctl@plt>
```
`%rsi` is a 64-bit register, on the line 1 value of `0x28(%r14)` is loaded to this register. That address points to `options.parentDeathSignal_`, which is a 32-bit value, set to 10 somewhere in a test. After that load:
```
rsi            0x7f000000000a
```
Notice it is not 10 (0xa), there is some garbage value in the upper part of the register. On the line 2, the lower part of this register is checked if it is zero, which corresponds to the first if statement. Then lines 4-8 prepare for `prctl` call. The value of the second argument is passed via `%rsi`, but the upper 32 bits were not cleared. This makes the function call generate `Invalid argument` error.
With the added explicit cast, notice a call `movslq %eax,%rsi`, which moves a signed 32-bit value of `%eax` (which contains `options.parentDeathSignal_`) to unsigned 64-bin `%rsi`:
```
   0x000000000040a77b <+347>:   mov    0x28(%r14),%rax
   0x000000000040a77f <+351>:   test   %eax,%eax
   0x000000000040a781 <+353>:   je     0x40a7a4 <folly::Subprocess::prepareChild(folly::Subprocess::Options const&, __sigset_t const*, char const*) const+388>
   0x000000000040a783 <+355>:   movslq %eax,%rsi
   0x000000000040a786 <+358>:   mov    $0x1,%edi
   0x000000000040a78b <+363>:   xor    %edx,%edx
   0x000000000040a78d <+365>:   xor    %ecx,%ecx
   0x000000000040a78f <+367>:   xor    %r8d,%r8d
   0x000000000040a792 <+370>:   xor    %eax,%eax
   0x000000000040a794 <+372>:   callq  0x405ad0 <prctl@plt>
```

Reviewed By: yfeldblum

Differential Revision: D3051611

fb-gh-sync-id: fc0f809bc4be0eed79dc5a701717efa27fedc022
shipit-source-id: fc0f809bc4be0eed79dc5a701717efa27fedc022

folly/Subprocess.cpp

index de5b109e33a6566e179b37ceac010650f5a2460a..c40630a5f7f59dace01854336f4e9bc78cd5e8c9 100644 (file)
@@ -480,7 +480,9 @@ int Subprocess::prepareChild(const Options& options,
 #if __linux__
   // Opt to receive signal on parent death, if requested
   if (options.parentDeathSignal_ != 0) {
-    if (prctl(PR_SET_PDEATHSIG, options.parentDeathSignal_, 0, 0, 0) == -1) {
+    const auto parentDeathSignal =
+        static_cast<unsigned long>(options.parentDeathSignal_);
+    if (prctl(PR_SET_PDEATHSIG, parentDeathSignal, 0, 0, 0) == -1) {
       return errno;
     }
   }