LCOV - code coverage report
Current view: directory - src/trusted/nonnacl_util/posix - sel_ldr_launcher_posix.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 50 32 64.0 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : 
       8                 : #include <sys/types.h>
       9                 : #include <sys/wait.h>
      10                 : 
      11                 : #include <assert.h>
      12                 : #include <fcntl.h>
      13                 : #include <libgen.h>
      14                 : #include <signal.h>
      15                 : #include <stdio.h>
      16                 : #include <string.h>
      17                 : #include <sys/param.h>
      18                 : #include <unistd.h>
      19                 : 
      20                 : #include "native_client/src/include/nacl_macros.h"
      21                 : #include "native_client/src/include/nacl_string.h"
      22                 : #include "native_client/src/shared/platform/nacl_check.h"
      23                 : #include "native_client/src/shared/platform/nacl_exit.h"
      24                 : #include "native_client/src/shared/platform/nacl_log.h"
      25                 : #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
      26                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      27                 : 
      28                 : 
      29                 : using std::vector;
      30                 : 
      31                 : namespace nacl {
      32                 : 
      33              11 : SelLdrLauncher::~SelLdrLauncher() {
      34              11 :   CloseHandlesAfterLaunch();
      35              11 :   if (kInvalidHandle != child_process_) {
      36                 :     int status;
      37                 :     // Ensure child process (service runtime) is kaput.  NB: we might
      38                 :     // close the command channel (or use the hard_shutdown RPC) rather
      39                 :     // than killing the process to allow the service runtime to do
      40                 :     // clean up, but the plugin should be responsible for that and we
      41                 :     // shouldn't introduce any timeout wait in a dtor.  Currently,
      42                 :     // ServiceRuntime::Shutdown kills the subprocess before closing
      43                 :     // the command channel, so we aren't providing the opportunity for
      44                 :     // a more graceful shutdown.
      45              10 :     KillChildProcess();
      46              10 :     waitpid(child_process_, &status, 0);
      47                 :   }
      48              11 :   if (kInvalidHandle != channel_) {
      49               0 :     Close(channel_);
      50                 :   }
      51              11 : }
      52                 : 
      53                 : 
      54               0 : nacl::string SelLdrLauncher::GetSelLdrPathName() {
      55                 :   char buffer[FILENAME_MAX];
      56               0 :   GetPluginDirectory(buffer, sizeof(buffer));
      57               0 :   return nacl::string(buffer) + "/sel_ldr";
      58                 : }
      59                 : 
      60              12 : nacl::string SelLdrLauncher::GetSelLdrBootstrapPathName() {
      61                 : #if NACL_LINUX
      62                 :   char buffer[FILENAME_MAX];
      63                 :   GetPluginDirectory(buffer, sizeof(buffer));
      64                 :   return nacl::string(buffer) + "/nacl_helper_bootstrap";
      65                 : #else
      66              12 :   return nacl::string(NACL_NO_FILE_PATH);
      67                 : #endif
      68                 : }
      69                 : 
      70              11 : Handle SelLdrLauncher::ExportImcFD(int dest_fd) {
      71                 :   Handle pair[2];
      72              11 :   if (SocketPair(pair) == -1) {
      73               0 :     return kInvalidHandle;
      74                 :   }
      75                 : 
      76              11 :   int rc = fcntl(pair[0], F_SETFD, FD_CLOEXEC);
      77              11 :   CHECK(rc == 0);
      78              11 :   close_after_launch_.push_back(pair[1]);
      79                 : 
      80              11 :   sel_ldr_argv_.push_back("-i");
      81              22 :   sel_ldr_argv_.push_back(ToString(dest_fd) + ":" + ToString(pair[1]));
      82              11 :   return pair[0];
      83                 : }
      84                 : 
      85                 : const size_t kMaxExecArgs = 64;
      86                 : 
      87              11 : bool SelLdrLauncher::LaunchFromCommandLine() {
      88              11 :   if (channel_number_ != -1) {
      89              11 :     channel_ = ExportImcFD(channel_number_);
      90                 :   }
      91                 : 
      92                 :   // complete command line setup
      93              11 :   vector<nacl::string> command;
      94              11 :   BuildCommandLine(&command);
      95              11 :   if (kMaxExecArgs <= command.size()) {
      96                 :     // TODO(robertm): emit error message
      97               0 :     return false;
      98                 :   }
      99                 :   // Set environment variable to keep the Mac sel_ldr from stealing the focus.
     100                 :   // TODO(sehr): change this to use a command line parameter rather than env.
     101              11 :   setenv("NACL_LAUNCHED_FROM_BROWSER", "1", 0);
     102                 :   // Fork the sel_ldr process.
     103              11 :   child_process_ = fork();
     104              11 :   if (child_process_ == -1) {
     105               0 :     return false;
     106                 :   }
     107                 : 
     108              11 :   if (child_process_ == 0) {
     109                 :     // convert vector -> array assuming no more than kMaxArgs
     110                 :     // NOTE: we also check this above so the assert should never fire
     111               0 :     assert(command.size() < kMaxExecArgs);
     112                 :     const char* argv[kMaxExecArgs];
     113               0 :     for (size_t i = 0; i < command.size(); ++i) {
     114               0 :       argv[i] = command[i].c_str();
     115                 :     }
     116               0 :     argv[command.size()] = NULL;
     117                 : 
     118               0 :     execv(argv[0], const_cast<char**>(argv));
     119               0 :     NaClLog(LOG_ERROR, "execv failed, args were:\n");
     120               0 :     for (size_t i = 0; i < command.size(); ++i) {
     121               0 :       NaClLog(LOG_ERROR, "%s\n", argv[i]);
     122                 :     }
     123               0 :     perror("execv");
     124               0 :     NaClExit(EXIT_FAILURE);
     125                 :   }
     126              11 :   CloseHandlesAfterLaunch();
     127              11 :   return true;
     128                 : }
     129                 : 
     130              10 : bool SelLdrLauncher::KillChildProcess() {
     131              10 :   if (kInvalidHandle == child_process_) {
     132                 :     // It is incorrect to use the kill syscall on kInvalidHandle as
     133                 :     // the pid, since using -1 as pid is defined by POSIX.1-2001 to
     134                 :     // send the signal (SIGKILL) to every process that the calling
     135                 :     // process may send signals to (except for init), which is
     136                 :     // Definitely Not What Was Intended for this.
     137               0 :     return true;
     138                 :   }
     139              10 :   return 0 == kill(child_process_, SIGKILL);
     140                 :   // We cannot set child_process_ to kInvalidHandle since we will want to wait
     141                 :   // on its exit status.
     142                 : }
     143                 : 
     144                 : }  // namespace nacl

Generated by: LCOV version 1.7