process.cpp 4.3 KB
Newer Older
羽飞's avatar
羽飞 已提交
1
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
羽飞's avatar
羽飞 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */

//
// Created by Longda on 2010
//

#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>

#include <string>

#include "common/io/io.h"
#include "common/log/log.h"
#include "common/os/path.h"
#include "common/os/process.h"
namespace common {

#ifdef __MACH__
#include <libgen.h>
#endif

33 34
#define MAX_ERR_OUTPUT 10000000  // 10M
#define MAX_STD_OUTPUT 10000000  // 10M
羽飞's avatar
羽飞 已提交
35 36 37

#define RWRR (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

38 39
std::string get_process_name(const char *prog_name)
{
羽飞's avatar
羽飞 已提交
40 41 42 43 44 45 46 47
  std::string process_name;

  int buf_len = strlen(prog_name);

  assert(buf_len);

  char *buf = new char[buf_len + 1];
  if (buf == NULL) {
48
    std::cerr << "Failed to alloc memory for program name." << SYS_OUTPUT_FILE_POS << SYS_OUTPUT_ERROR << std::endl;
羽飞's avatar
羽飞 已提交
49 50 51 52 53 54 55 56 57 58 59 60 61
    return "";
  }
  memset(buf, 0, buf_len + 1);
  strncpy(buf, prog_name, buf_len);

  process_name = basename(buf);

  delete[] buf;
  return process_name;
}

// Background the process by detaching it from the console and redirecting
// std in, out, and err to /dev/null
62 63
int daemonize_service(bool close_std_streams)
{
羽飞's avatar
羽飞 已提交
64 65
  int nochdir = 1;
  int noclose = close_std_streams ? 0 : 1;
L
Longda Feng 已提交
66 67 68 69
#ifdef __MACH__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
羽飞's avatar
羽飞 已提交
70
  int rc = daemon(nochdir, noclose);
L
Longda Feng 已提交
71 72 73
#ifdef __MACH__
#pragma GCC diagnostic pop
#endif
羽飞's avatar
羽飞 已提交
74 75 76 77 78 79 80
  // Here after the fork; the parent is dead and setsid() is called
  if (rc != 0) {
    std::cerr << "Error: unable to daemonize: " << strerror(errno) << "\n";
  }
  return rc;
}

81 82
int daemonize_service(const char *std_out_file, const char *std_err_file)
{
羽飞's avatar
羽飞 已提交
83 84 85 86 87 88 89 90 91 92 93 94
  int rc = daemonize_service(false);

  if (rc != 0) {
    std::cerr << "Error: \n";
    return rc;
  }

  sys_log_redirect(std_out_file, std_err_file);

  return 0;
}

95 96
void sys_log_redirect(const char *std_out_file, const char *std_err_file)
{
羽飞's avatar
羽飞 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
  int rc = 0;

  // Redirect stdin to /dev/null
  int nullfd = open("/dev/null", O_RDONLY);
  if (nullfd >= 0) {
    dup2(nullfd, STDIN_FILENO);
    close(nullfd);
  }

  // Get timestamp.
  struct timeval tv;
  rc = gettimeofday(&tv, NULL);
  if (rc != 0) {
    std::cerr << "Fail to get current time" << std::endl;
    tv.tv_sec = 0;
  }

  int std_err_flag, std_out_flag;
  // Always use append-write. And if not exist, create it.
  std_err_flag = std_out_flag = O_CREAT | O_APPEND | O_WRONLY;

  std::string err_file = getAboslutPath(std_err_file);

120
  // CWE367: A check occurs on a file's attributes before the file is
羽飞's avatar
羽飞 已提交
121 122 123 124 125 126 127 128 129
  // used in a privileged operation, but things may have changed
  // Redirect stderr to std_err_file
  // struct stat st;
  // rc = stat(err_file.c_str(), &st);
  // if (rc != 0 || st.st_size > MAX_ERR_OUTPUT) {
  //   // file may not exist or oversize
  //   std_err_flag |= O_TRUNC; // Remove old content if any.
  // }

130
  std_err_flag |= O_TRUNC;  // Remove old content if any.
羽飞's avatar
羽飞 已提交
131 132 133 134 135 136

  int errfd = open(err_file.c_str(), std_err_flag, RWRR);
  if (errfd >= 0) {
    dup2(errfd, STDERR_FILENO);
    close(errfd);
  }
137 138
  setvbuf(stderr, NULL, _IONBF, 0);  // Make sure stderr is not buffering
  std::cerr << "Process " << getpid() << " built error output at " << tv.tv_sec << std::endl;
羽飞's avatar
羽飞 已提交
139 140 141 142 143 144 145 146 147 148

  std::string outFile = getAboslutPath(std_out_file);

  // Redirect stdout to outFile.c_str()
  // rc = stat(outFile.c_str(), &st);
  // if (rc != 0 || st.st_size > MAX_STD_OUTPUT) {
  //   // file may not exist or oversize
  //   std_out_flag |= O_TRUNC; // Remove old content if any.
  // }

149
  std_out_flag |= O_TRUNC;  // Remove old content if any.
羽飞's avatar
羽飞 已提交
150 151 152 153 154
  int outfd = open(outFile.c_str(), std_out_flag, RWRR);
  if (outfd >= 0) {
    dup2(outfd, STDOUT_FILENO);
    close(outfd);
  }
155 156
  setvbuf(stdout, NULL, _IONBF, 0);  // Make sure stdout not buffering
  std::cout << "Process " << getpid() << " built standard output at " << tv.tv_sec << std::endl;
羽飞's avatar
羽飞 已提交
157 158 159 160

  return;
}

161
}  // namespace common