<commit_before>// vim: sw=2

// Hook functions are declared with extern "C", because we want to disable
// the C++ name mangling and make the instrumentation easier.


#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <errno.h>
#include <iostream>
#include <pthread.h>
#include <signal.h>
#include <stack>
#include <string>
#include <sstream>
#include <unistd.h>
#include <vector>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>

#include "rcs/IDAssigner.h"

#include "dyn-aa/LogRecord.h"

using namespace std;
using namespace rcs;
using namespace dyn_aa;

static string LogDirName;
static __thread FILE *MyLogFile = NULL;
static vector<FILE *> LogFiles;
static pthread_mutex_t Lock = PTHREAD_MUTEX_INITIALIZER;
static __thread int NumActualArgs;
// These two thread-specific flags are used to workaround the issue with signal
// handling.
static __thread bool IsLogging = false;
static __thread bool DisableLogging = false;

static string GetLogFileName(pid_t ThreadID) {
  ostringstream OS;
  OS << LogDirName << "/pts-" << ThreadID;
  return OS.str();
}

static string GetLogFileName() {
  pid_t ThreadID = syscall(SYS_gettid);
  return GetLogFileName(ThreadID);
}

// TODO: The Append flag is not necessary. We could just uniformly use "ab".
static void OpenLogFile(bool Append) {
  MyLogFile = fopen(GetLogFileName().c_str(), Append ? "ab" : "wb");
  if (!MyLogFile)
    perror("fopen");
  assert(MyLogFile);
  pthread_mutex_lock(&Lock);
  LogFiles.push_back(MyLogFile);
  pthread_mutex_unlock(&Lock);
}

static void OpenLogFileIfNecessary() {
  if (!MyLogFile)
    OpenLogFile(false);
}

extern "C" void FinalizeMemHooks() {
  pthread_mutex_lock(&Lock);
  for (size_t i = 0; i < LogFiles.size(); ++i) {
    assert(LogFiles[i]);
    fclose(LogFiles[i]);
  }
  pthread_mutex_unlock(&Lock);
}

extern "C" void InitMemHooks() {
  // Set the log directory name.
  if (const char *LogDirEnv = getenv("LOG_DIR")) {
    LogDirName = LogDirEnv;
  } else {
    time_t T = time(NULL);
    struct tm *LT = localtime(&T);
    char LogDirNameCStr[1024];
    sprintf(LogDirNameCStr, "/tmp/ng-%04d%02d%02d-%02d%02d%02d",
            LT->tm_year + 1900, LT->tm_mon + 1, LT->tm_mday,
            LT->tm_hour, LT->tm_min, LT->tm_sec);
    LogDirName = LogDirNameCStr;
  }
  // Craete the logging directory if doesn't exist.
  int R = mkdir(LogDirName.c_str(), 0755);
  if (R == -1) {
    if (errno != EEXIST)
      assert(false);
    // Clear old log files in the log directory.
    system(("rm -f " + LogDirName + "/pts-*").c_str());
  }
  atexit(FinalizeMemHooks);
}

static void PrintLogRecord(const LogRecord &Record) {
  // FIXME: Signal handler can happen anytime even if during the fwrite, causing
  // the log to be broken. To workaround this issue, PrintLogRecord sets
  // IsLogging at the beginning, and resets it at the end. If PrintLogRecord
  // is entered with IsLogging on, the thread is probably inside a signal
  // handler. In that case, we simply disable future logging. This approach is
  // sure problematic because it misses logs, but it is not a big deal for now,
  // because the signal is usually generated at the end of the execution when
  // the user wants to terminate the server. A better approach would be to
  // figure out statically which functions are signal handlers, and only disable
  // logging inside the life cycles of these signal handlers.
  if (IsLogging)<commit_msg>Fixed a warning on an unused return value<commit_after>// vim: sw=2

// Hook functions are declared with extern "C", because we want to disable
// the C++ name mangling and make the instrumentation easier.


#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <errno.h>
#include <iostream>
#include <pthread.h>
#include <signal.h>
#include <stack>
#include <string>
#include <sstream>
#include <unistd.h>
#include <vector>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>

#include "rcs/IDAssigner.h"

#include "dyn-aa/LogRecord.h"

using namespace std;
using namespace rcs;
using namespace dyn_aa;

static string LogDirName;
static __thread FILE *MyLogFile = NULL;
static vector<FILE *> LogFiles;
static pthread_mutex_t Lock = PTHREAD_MUTEX_INITIALIZER;
static __thread int NumActualArgs;
// These two thread-specific flags are used to workaround the issue with signal
// handling.
static __thread bool IsLogging = false;
static __thread bool DisableLogging = false;

static string GetLogFileName(pid_t ThreadID) {
  ostringstream OS;
  OS << LogDirName << "/pts-" << ThreadID;
  return OS.str();
}

static string GetLogFileName() {
  pid_t ThreadID = syscall(SYS_gettid);
  return GetLogFileName(ThreadID);
}

// TODO: The Append flag is not necessary. We could just uniformly use "ab".
static void OpenLogFile(bool Append) {
  MyLogFile = fopen(GetLogFileName().c_str(), Append ? "ab" : "wb");
  if (!MyLogFile)
    perror("fopen");
  assert(MyLogFile);
  pthread_mutex_lock(&Lock);
  LogFiles.push_back(MyLogFile);
  pthread_mutex_unlock(&Lock);
}

static void OpenLogFileIfNecessary() {
  if (!MyLogFile)
    OpenLogFile(false);
}

extern "C" void FinalizeMemHooks() {
  pthread_mutex_lock(&Lock);
  for (size_t i = 0; i < LogFiles.size(); ++i) {
    assert(LogFiles[i]);
    fclose(LogFiles[i]);
  }
  pthread_mutex_unlock(&Lock);
}

extern "C" void InitMemHooks() {
  // Set the log directory name.
  if (const char *LogDirEnv = getenv("LOG_DIR")) {
    LogDirName = LogDirEnv;
  } else {
    time_t T = time(NULL);
    struct tm *LT = localtime(&T);
    char LogDirNameCStr[1024];
    sprintf(LogDirNameCStr, "/tmp/ng-%04d%02d%02d-%02d%02d%02d",
            LT->tm_year + 1900, LT->tm_mon + 1, LT->tm_mday,
            LT->tm_hour, LT->tm_min, LT->tm_sec);
    LogDirName = LogDirNameCStr;
  }
  // Craete the logging directory if doesn't exist.
  int R = mkdir(LogDirName.c_str(), 0755);
  if (R == -1) {
    if (errno != EEXIST)
      assert(false);
    // Clear old log files in the log directory.
    R = system(("rm -f " + LogDirName + "/pts-*").c_str());
    assert(R != -1);
  }
  atexit(FinalizeMemHooks);
}

static void PrintLogRecord(const LogRecord &Record) {
  // FIXME: Signal handler can happen anytime even if during the fwrite, causing
  // the log to be broken. To workaround this issue, PrintLogRecord sets
  // IsLogging at the beginning, and resets it at the end. If PrintLogRecord
  // is entered with IsLogging on, the thread is probably inside a signal
  // handler. In that case, we simply disable future logging. This approach is
  // sure problematic because it misses logs, but it is not a big deal for now,
  // because the signal is usually generated at the end of the execution when
  // the user wants to terminate the server. A better approach would be to
  // figure out statically which functions are signal handlers, and only disable
  // logging inside the life cycles of these signal handlers.
  if (IsLogging)
{'fraction_non_alphanumeric': 0.11745397459683174, 'fraction_numerical': 0.008134722420436707, 'mean_word_length': 3.9213483146067416, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1669411', 'n_tokens_mistral': 2391, 'n_tokens_neox': 2303, 'n_words': 767}