C API mysql_real_connect throw Segmentation fault (core dumped) when it is build by node-gyp

115 Views Asked by At

Issue

I could run the function dosomething() when it is compiled with g++ directly. But I could not run it when it is build with node-gyp. I was able to narrow my issue down to just a few files, I am hoping that some of you can get me out from here. Thanks in advance :-)

I observed:

  • when host=localhost, execute successfully when build with node-gyp
  • when host=localhost or external IP, execute successfully when build with g++ -o conn $(mysql_config --cflags) test_db_conn.cpp -std=c++17 $(mysql_config --libs)
  • no error code, only Segmentation fault

I did:

  • set bind-address=0.0.0.0
  • add target host to /etc/hosts (I am able to connect to the host DB from the terminal) and call it "jonah", I was able to ping and execute the program with the "jonah" as host

I am certain:

  • None of the characters used in the credential needs to be escaped

Environment:

  • OS: Ubuntu 22.04.02 LTS (server)
  • Node: v16.20.0
  • node-gyp: ^9.4.0
  • MySQL: Ver 8.0.35-0ubuntu0.22.04.1
  • MySQL C API: Ver 8
// test_db_conn.cpp
/**
 *
 * g++ -o conn $(mysql_config --cflags) test_db_conn.cpp -std=c++17
 * $(mysql_config --libs)
 *
 */
#include <mysql.h>

#include <cstring>
#include <iostream>
void dosomething();

int main() {
  dosomething();
  return 0;
}

void dosomething() {
  MYSQL *conn;
  MYSQL_RES *res;
  MYSQL_ROW row;
  constexpr int QUERY_STATEMENT_LEN = 512;

  char query[QUERY_STATEMENT_LEN] = {0}, *end_pos = nullptr;

  long lTime = 0;
  std::string stmt = "SELECT MIN(time) FROM Log";
  std::cout << stmt << '\n';
  try {
    end_pos = stpcpy(query, stmt.c_str());

    conn = mysql_init(NULL);

    const char *host = "IP"; // 172.x.x.x
    const char *user = "username";
    const char *password = "password";
    const char *database = "dbname";
    const int port = 3306;
    if (!mysql_real_connect(conn, host, user, password, database, port, NULL, 0)) {
      throw mysql_error(conn);
    }
    if (mysql_real_query(conn, query, (unsigned int)(end_pos - query))) {
      throw mysql_error(conn);
    }
    res = mysql_use_result(conn);

    while ((row = mysql_fetch_row(res)) != NULL) {
      if (row[0] == NULL) break;
      lTime = std::stol(row[0]);
      break;
    }
    // release resources
    mysql_free_result(res);
    mysql_close(conn);
    std::cout << "ltime " << lTime << '\n';
  } catch (const char *e) {
    if (res) mysql_free_result(res);
    if (conn) mysql_close(conn);
    std::cerr << "e " << e << '\n';
    throw e;
  }
}
// CMySQL.h
#ifndef CMYSQL_H
#define CMYSQL_H

#include <mysql.h>  // find /usr/ -type f -name mysql.h
#include <node.h>   // find /usr/ -type f -name node.h
#include <node_object_wrap.h>

#include <cstring>
#include <exception>
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include "DBCredential.h"

class CMySQL : public node::ObjectWrap {
 private:
  DBCredential m_db;
  void dosomething();

 public:
  explicit CMySQL(const DBCredential db) : m_db(db) {}
  ~CMySQL() {}
  static void Init(v8::Local<v8::Object> exports);
  static void New(const v8::FunctionCallbackInfo<v8::Value> &args);
  static void pull(const v8::FunctionCallbackInfo<v8::Value> &args);
};
#endif
// binding.gyp
{
    "targets":[
        {
            "target_name": "CMySQL_Addon",
            "sources": [
                "./DBCredential.cc",
                "./CMySQL.cc",
                "./MySQL_Addon.cc"
            ],
            "cflags_cc":[
                "-fexceptions",
                "-std=c++17"
            ],
            "cflags": [
                "-I/usr/include/mysql"
            ],
            "libraries": [
                "-L/usr/lib/x86_64-linux-gnu",
                "-lmysqlclient",
                "-lzstd",
                "-lssl",
                "-lcrypto",
                "-lresolv",
                "-lm",
                "-lz"
            ],
            "make_global_settings": [
                {
                    "CC": ["/usr/bin/g++"]
                }
            ]
        }
    ]
}
0

There are 0 best solutions below