libpqxx freezes on connection::prepare - c++

My program should synchronize with remote postgres database. My code:
db_handler::DB_Handler::DB_Handler(const char* host, unsigned int port, const char* db, const char* user, const char* password, int& error) {
...
this->password = reinterpret_cast<char*>(malloc(std::strlen(password) + 1));
strcpy(this->password, password);
this->connection = nullptr;
if (this->connect_to_db() != 0) {
error = 1;
}
else {
error = 0;
}
}
int db_handler::DB_Handler::connect_to_db() {
try {
std::string connection_params = "host=";
connection_params += std::string(host);
...
connection_params += " password=";
connection_params += password;
if (this->connection != nullptr) {
delete this->connection;
}
this->connection = new pqxx::connection(connection_params.c_str());
return 0;
}
catch (...) {
return 1;
}
}
int db_handler::DB_Handler::sync() {
for (int tries = 0; tries < 2; tries++) {
try {
this->connection->prepare("get_keys", "*query here*");
...
}
catch (const pqxx::broken_connection& e) {
this->connect_to_db();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
catch (...) {
return 1;
}
}
return 1;
}
And on this row this->connection->prepare("get_keys", "*query here*"); my program freezes forever until I will restart it.
Where am I wrong and how can I fix it?
Maybe I should add some timeouts? How can I do it?

Related

In Visual Studio, After passing parameters by pointer or reference of visual studio function, the access parameter value in the function is null

This is the main code where error happened:
void VRInputRemapping::DigitalInputConfig() {
bool orginput = this->curVRConfig->GetorgDigitalInput();
uint32_t deviceId = this->curVRConfig->GetcurDeviceId();
uint32_t buttonId = this->curVRConfig->GetcurButtonId();
printf("Digital orginput: %d device:%d butonid:%d\n", orginput, deviceId, buttonId);
vrinputemulator::DigitalInputRemapping* m_currentRemapping =new vrinputemulator::DigitalInputRemapping(true);
vrinputemulator::DigitalBinding* m_currentBinding = new vrinputemulator::DigitalBinding;
if (orginput == false) {
m_currentBinding->type = vrinputemulator::DigitalBindingType::Disabled;
memset(&m_currentBinding->data, 0, sizeof(m_currentBinding->data));
m_currentBinding->data.openvr.buttonId = buttonId;
m_currentBinding->toggleEnabled = false;
m_currentBinding->toggleDelay = 0;
m_currentBinding->autoTriggerEnabled = false;
m_currentBinding->autoTriggerFrequency = 1;
m_currentRemapping->binding = *m_currentBinding;
}
else if (orginput == true) {
m_currentBinding->type = vrinputemulator::DigitalBindingType::NoRemapping;
memset(&m_currentBinding->data, 0, sizeof(m_currentBinding->data));
m_currentBinding->data.openvr.buttonId = buttonId;
m_currentBinding->toggleEnabled = false;
m_currentBinding->toggleDelay = 0;
m_currentBinding->autoTriggerEnabled = false;
m_currentBinding->autoTriggerFrequency = 1;
m_currentRemapping->binding = *m_currentBinding;
}
printf(" void VRInputRemapping::DigitalInputConfig() m_currentRemapping->binding.type:%d device:%d buttonId:%d remapping.data.openvr.buttonId%d\n", m_currentRemapping->binding.type, deviceId, buttonId, m_currentRemapping->binding.data.openvr.buttonId);
//<--------------------Here is the function call-------------------------------------->
this->inputEmulator->setDigitalInputRemapping(deviceId, buttonId, m_currentRemapping);
//<--------------------Here is the function call-------------------------------------->
printf(" void VRInputRemapping::DigitalInputConfig() m_currentRemapping->binding.type:%d device:%d buttonId:%d remapping.data.openvr.buttonId%d\n", m_currentRemapping->binding.type, deviceId, buttonId, m_currentRemapping->binding.data.openvr.buttonId);
delete m_currentBinding;
delete m_currentRemapping;
Sleep(1);
}
This is the Function:
void VRInputEmulator::setDigitalInputRemapping(uint32_t deviceId, uint32_t buttonId, DigitalInputRemapping* remapping, bool modal) {
printf("VRInputEmulator::setDigitalInputRemapping Digital orginput: %d device:%d butonid:%d remapping->binding.data.openvr.buttonId%d\n", remapping->binding.type, deviceId, buttonId, remapping->binding.data.openvr.buttonId);
if (_ipcServerQueue) {
ipc::Request message(ipc::RequestType::InputRemapping_SetDigitalRemapping);
memset(&message.msg, 0, sizeof(message.msg));
message.msg.ir_SetDigitalRemapping.clientId = m_clientId;
message.msg.ir_SetDigitalRemapping.messageId = 0;
message.msg.ir_SetDigitalRemapping.controllerId = deviceId;
message.msg.ir_SetDigitalRemapping.buttonId = buttonId;
message.msg.ir_SetDigitalRemapping.remapData = *remapping;
if (modal) {
uint32_t messageId = _ipcRandomDist(_ipcRandomDevice);
message.msg.ir_SetDigitalRemapping.messageId = messageId;
std::promise<ipc::Reply> respPromise;
auto respFuture = respPromise.get_future();
{
std::lock_guard<std::recursive_mutex> lock(_mutex);
_ipcPromiseMap.insert({ messageId, std::move(respPromise) });
}
_ipcServerQueue->send(&message, sizeof(ipc::Request), 0);
auto resp = respFuture.get();
{
std::lock_guard<std::recursive_mutex> lock(_mutex);
_ipcPromiseMap.erase(messageId);
}
std::stringstream ss;
ss << "Error while setting digital input remapping: ";
if (resp.status == ipc::ReplyStatus::InvalidId) {
ss << "Invalid device id";
throw vrinputemulator_invalidid(ss.str(), (int)resp.status);
} else if (resp.status == ipc::ReplyStatus::NotFound) {
ss << "Device not found";
throw vrinputemulator_notfound(ss.str(), (int)resp.status);
} else if (resp.status != ipc::ReplyStatus::Ok) {
ss << "Error code " << (int)resp.status;
throw vrinputemulator_exception(ss.str(), (int)resp.status);
}
} else {
_ipcServerQueue->send(&message, sizeof(ipc::Request), 0);
}
} else {
throw vrinputemulator_connectionerror("No active connection.");
}
}
You can See the Printf I had use before and after the function call, also used in the head of the dunction,This is the output:
void VRInputRemapping::DigitalInputConfig() m_currentRemapping->binding.type:0 device:1 buttonId:32 remapping.data.openvr.buttonId: 32
VRInputEmulator::setDigitalInputRemapping Digital orginput: 0 device:1 butonid:32 remapping->binding.data.openvr.buttonId: 0
void VRInputRemapping::DigitalInputConfig() m_currentRemapping->binding.type 0 device:1 buttonId:32 remapping.data.openvr.buttonId: 32
The output in the consloe

Data race while reading contents of archive with libarchive in thread. What I did wrong?

I`m trying to parallelize reading and processing archives, that are already in memory, but I get data race while calling libarchive function in a thread. Google sanitizer says that problem is in calling archive_read_open_memory function inside get_archive_contens. But I read that all functions in libarchive should be thread-safe. Can anyone tell me what I did wrong?
Here is my thread code.
void indexing_thread(std::mutex &m,
int &current_indexing_threads, concurrent_queue<std::pair<std::string, std::string>> &raw_files_q,
concurrent_queue<std::map<std::string, size_t>> &words_q) {
while (true) {
auto raw_file = raw_files_q.front();
std::string file_buffer = raw_file.first;
std::string ext = raw_file.second;
if (file_buffer.empty() && ext.empty()) {
break;
}
raw_files_q.pop();
std::string file_content;
if (ext == ".zip") {
auto archive_contents = get_archive_content(file_buffer);
for (int i = 0; i < archive_contents.size(); ++i) {
auto cur_ext = boost::filesystem::extension(archive_contents[i]);
if (cur_ext == ".txt") {
file_content = get_archive_file_contents(archive_contents[i], archive_contents, file_buffer);
file_content = convert_to_normalized_utf_string(file_content);
}
}
for (int i = 0; i < archive_contents.size(); ++i) {
auto cur_ext = boost::filesystem::extension(archive_contents[i]);
if (cur_ext == ".txt") {
file_content = get_archive_file_contents(archive_contents[i], archive_contents, file_buffer);
file_content = convert_to_normalized_utf_string(file_content);
}
}
}
auto words = word_count_map_nonparallel(file_content);
words_q.push_back(words);
}
m.lock();
current_indexing_threads--;
if (current_indexing_threads == 0) {
words_q.push_back(std::map<std::string, size_t>{});
}
m.unlock();
}
get_archive_content code:
std::string
get_archive_file_contents(const std::string &filename, std::vector<std::string> contents, std::string file_buffer) {
if (std::find(contents.begin(), contents.end(), filename) == contents.end()) {
throw FileDoesNotExistsException(filename);
}
struct archive_entry *entry;
struct archive *archive = archive_read_new();
archive_read_support_filter_all(archive);
archive_read_support_format_all(archive);
archive_read_support_format_raw(archive);
archive_read_support_format_empty(archive);
int reading_result = archive_read_open_memory(archive, file_buffer.data(), file_buffer.size());
if (reading_result != 0) {
throw std::runtime_error("Error reading archive");
}
void *buf;
int64_t length;
while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
if (archive_entry_filetype(entry) == AE_IFREG) {
length = archive_entry_size(entry);
buf = malloc(length);
if (!buf) {
archive_read_data_skip(archive);
continue;
}
archive_read_data(archive, buf, length);
break;
}
}
std::string result = static_cast<char *>(buf);
return result;
}
UPD: Google thread sanitizer report
I worked it out. The problem was in binary, that gets installed from ubuntu repositories. I solved this problem install libarchive from the sources.

C++ [Microsoft][ODBC SQL Server Driver]String data, right truncation

I need help with ODBC prepared queries. I working on Windows 10(x64). My VPS server is Windows Server 2012(x64). My compiled aplication is 32 bit. I need prepared queries to make SQL Injection not possible. But have one big problem.
Error:
[QueryManager] State (22001), Diagnostic: [Microsoft][ODBC SQL Server Driver]String data, right truncation
Code:
gQueryManager.BindParameterAsString(1,Name,sizeof(Name));
gQueryManager.ExecQuery("SELECT Value FROM Table WHERE Name=?");
gQueryManager.Fetch();
...
gQueryManager.Close();
This is source code of Query Manager I using:
// QueryManager.cpp: implementation of the CQueryManager class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "QueryManager.h"
#include "Util.h"
CQueryManager gQueryManager;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CQueryManager::CQueryManager() // OK
{
this->m_SQLEnvironment = SQL_NULL_HANDLE;
this->m_SQLConnection = SQL_NULL_HANDLE;
this->m_STMT = SQL_NULL_HANDLE;
this->m_RowCount = -1;
this->m_ColCount = -1;
memset(this->m_SQLColName,0,sizeof(this->m_SQLColName));
memset(this->m_SQLData,0,sizeof(this->m_SQLData));
SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&this->m_SQLEnvironment);
SQLSetEnvAttr(this->m_SQLEnvironment,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);
}
CQueryManager::~CQueryManager() // OK
{
this->Disconnect();
}
bool CQueryManager::Connect(char* odbc,char* user,char* pass) // OK
{
strcpy_s(this->m_odbc,odbc);
strcpy_s(this->m_user,user);
strcpy_s(this->m_pass,pass);
if(SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_DBC,this->m_SQLEnvironment,&this->m_SQLConnection)) == 0)
{
return 0;
}
if(SQL_SUCCEEDED(SQLConnect(this->m_SQLConnection,(SQLCHAR*)this->m_odbc,SQL_NTS,(SQLCHAR*)this->m_user,SQL_NTS,(SQLCHAR*)this->m_pass,SQL_NTS)) == 0)
{
return 0;
}
if(SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_STMT,this->m_SQLConnection,&this->m_STMT)) == 0)
{
return 0;
}
else
{
return 1;
}
}
void CQueryManager::Disconnect() // OK
{
if(this->m_STMT != SQL_NULL_HANDLE)
{
SQLFreeHandle(SQL_HANDLE_STMT,this->m_STMT);
this->m_STMT = SQL_NULL_HANDLE;
}
if(this->m_SQLConnection != SQL_NULL_HANDLE)
{
SQLFreeHandle(SQL_HANDLE_DBC,this->m_SQLConnection);
this->m_SQLConnection = SQL_NULL_HANDLE;
}
if(this->m_SQLEnvironment != SQL_NULL_HANDLE)
{
SQLFreeHandle(SQL_HANDLE_ENV,this->m_SQLEnvironment);
this->m_SQLEnvironment = SQL_NULL_HANDLE;
}
}
void CQueryManager::Diagnostic(char* query) // OK
{
LogAdd(LOG_BLACK,"%s",query);
SQLINTEGER NativeError;
SQLSMALLINT RecNumber=1,BufferLength;
SQLCHAR SqlState[6],MessageText[SQL_MAX_MESSAGE_LENGTH];
while(SQLGetDiagRec(SQL_HANDLE_STMT,this->m_STMT,(RecNumber++),SqlState,&NativeError,MessageText,sizeof(MessageText),&BufferLength) != SQL_NO_DATA)
{
LogAdd(LOG_RED,"[QueryManager] State (%s), Diagnostic: %s",SqlState,MessageText);
}
if(strcmp((char*)SqlState,"08S01") == 0)
{
this->Connect(this->m_odbc,this->m_user,this->m_pass);
}
}
bool CQueryManager::ExecQuery(char* query,...) // OK
{
char buff[4096];
va_list arg;
va_start(arg,query);
vsprintf_s(buff,query,arg);
va_end(arg);
SQLRETURN result;
if(SQL_SUCCEEDED((result=SQLExecDirect(this->m_STMT,(SQLCHAR*)buff,SQL_NTS))) == 0 && result != SQL_NO_DATA)
{
this->Diagnostic(buff);
return 0;
}
SQLRowCount(this->m_STMT,&this->m_RowCount);
if(this->m_RowCount == 0){return 1;}
SQLNumResultCols(this->m_STMT,&this->m_ColCount);
if(this->m_ColCount == 0){return 1;}
if(this->m_ColCount > MAX_COLUMNS){return 0;}
memset(this->m_SQLColName,0,sizeof(this->m_SQLColName));
memset(this->m_SQLData,0,sizeof(this->m_SQLData));
for(int n=0;n < this->m_ColCount;n++)
{
SQLDescribeCol(this->m_STMT,(n+1),this->m_SQLColName[n],sizeof(this->m_SQLColName[n]),0,0,0,0,0);
SQLBindCol(this->m_STMT,(n+1),SQL_C_CHAR,this->m_SQLData[n],sizeof(this->m_SQLData[n]),&this->m_SQLDataLen[n]);
}
return 1;
}
void CQueryManager::Close() // OK
{
SQLCloseCursor(this->m_STMT);
SQLFreeStmt(this->m_STMT,SQL_UNBIND);
}
SQLRETURN CQueryManager::Fetch() // OK
{
return SQLFetch(this->m_STMT);
}
int CQueryManager::FindIndex(char* ColName) // OK
{
for(int n=0;n < this->m_ColCount;n++)
{
if(_stricmp(ColName,(char*)this->m_SQLColName[n]) == 0)
{
return n;
}
}
return -1;
}
int CQueryManager::GetResult(int index) // OK
{
return atoi(this->m_SQLData[index]);
}
int CQueryManager::GetAsInteger(char* ColName) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
return index;
}
else
{
return atoi(this->m_SQLData[index]);
}
}
float CQueryManager::GetAsFloat(char* ColName) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
return (float)index;
}
else
{
return (float)atof(this->m_SQLData[index]);
}
}
__int64 CQueryManager::GetAsInteger64(char* ColName) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
return index;
}
else
{
return _atoi64(this->m_SQLData[index]);
}
}
void CQueryManager::GetAsString(char* ColName,char* OutBuffer,int OutBufferSize) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
memset(OutBuffer,0,OutBufferSize);
}
else
{
strncpy_s(OutBuffer,OutBufferSize,this->m_SQLData[index],(OutBufferSize-1));
}
}
void CQueryManager::GetAsBinary(char* ColName,BYTE* OutBuffer,int OutBufferSize) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
memset(OutBuffer,0,OutBufferSize);
}
else
{
this->ConvertStringToBinary(this->m_SQLData[index],sizeof(this->m_SQLData[index]),OutBuffer,OutBufferSize);
}
}
void CQueryManager::BindParameterAsString(int ParamNumber,void* InBuffer,int ColumnSize) // OK
{
this->m_SQLBindValue[(ParamNumber-1)] = SQL_NTS;
SQLBindParameter(this->m_STMT,ParamNumber,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_VARCHAR,ColumnSize,0,InBuffer,0,&this->m_SQLBindValue[(ParamNumber-1)]);
}
void CQueryManager::BindParameterAsBinary(int ParamNumber,void* InBuffer,int ColumnSize) // OK
{
this->m_SQLBindValue[(ParamNumber-1)] = ColumnSize;
SQLBindParameter(this->m_STMT,ParamNumber,SQL_PARAM_INPUT,SQL_C_BINARY,SQL_VARBINARY,ColumnSize,0,InBuffer,0,&this->m_SQLBindValue[(ParamNumber-1)]);
}
void CQueryManager::ConvertStringToBinary(char* InBuff,int InSize,BYTE* OutBuff,int OutSize) // OK
{
int size = 0;
memset(OutBuff,0,OutSize);
for(int n=0;n < InSize,size < OutSize;n++)
{
if(InBuff[n] == 0)
{
break;
}
if((n%2) == 0)
{
OutBuff[size] = ((InBuff[n]>='A')?((InBuff[n]-'A')+10):(InBuff[n]-'0'))*16;
size = size+0;
}
else
{
OutBuff[size] = OutBuff[size] | ((InBuff[n]>='A')?((InBuff[n]-'A')+10):(InBuff[n]-'0'));
size = size+1;
}
}
}
void CQueryManager::ConvertBinaryToString(BYTE* InBuff,int InSize,char* OutBuff,int OutSize) // OK
{
int size = 0;
memset(OutBuff,0,OutSize);
for(int n=0;n < OutSize,size < InSize;n++)
{
if((n%2) == 0)
{
OutBuff[n] = (((InBuff[size]/16)>=10)?('A'+((InBuff[size]/16)-10)):('0'+(InBuff[size]/16)));
size = size+0;
}
else
{
OutBuff[n] = (((InBuff[size]%16)>=10)?('A'+((InBuff[size]%16)-10)):('0'+(InBuff[size]%16)));
size = size+1;
}
}
}

Pjsip multiple calls using few outgoing lines fails

I'm using pjsip high-level api PJSUA for doing multiple calls at one time. My sip operator support up to 3 outgoing lines for calls, so in theory it should be possible to call 3 persons at one time. The problem is, that in the operator logs i see, the message "Line limit overreached" and in pjsip, the call fails. I'm doing it like this:
Here is my class that contains methods for calling:
void Sip::InitLibrary()
{
pj::EpConfig ep_cfg;
ep_cfg.logConfig.level = 4;
ep_cfg.logConfig.consoleLevel = 4;
ep_cfg.logConfig.filename = this->log_;
ep_cfg.uaConfig.userAgent = "Ekiga";
this->ep_.libCreate();
this->ep_.libInit(ep_cfg);
}
void Sip::SetSipTransport(Sip::SipTransport transport, unsigned port)
{
TransportConfig tcfg;
tcfg.port = port;
pjsip_transport_type_e type;
switch (transport)
{
case SipTransport::TCP:
type = PJSIP_TRANSPORT_TCP;
break;
case SipTransport::UDP:
type = PJSIP_TRANSPORT_UDP;
break;
}
try {
this->transportId_ = this->ep_.transportCreate(type, tcfg);
}
catch (Error &err) {
//to log
return;
}
}
void Sip::StartLibrary()
{
this->ep_.libStart();
}
AccountInfo Sip::ConnectSipServer(string serv, string login, string pass,SipTransport transport,int port)
{
this->InitLibrary();
this->SetSipTransport(transport, port);
this->StartLibrary();
this->server_ = serv;
AccountConfig accConfig;
string uri = "<sip:" + login + "#" + serv +">";
accConfig.idUri = uri;
string regUri = "sip:" + serv;
accConfig.regConfig.registrarUri = regUri;
accConfig.sipConfig.authCreds.push_back(AuthCredInfo("digest", "*", login, 0, pass));
this->acc_ = new SipAccount();
acc_->create(accConfig, true);
{
unique_lock<mutex> locker(acc_->regLock_);
while (!acc_->regEnd_)
acc_->regDone_.wait(locker);
}
return acc_->info_;
}
bool Sip::CallNumber(string phone)
{
Call *call = new SipCall(*this->acc_);
CallOpParam prm(true);
prm.opt.audioCount = 1;
prm.opt.videoCount = 0;
call->makeCall("sip:" + phone + "#" + this->server_, prm);
SipCall *myCall = (SipCall*)call;
{
unique_lock<mutex> locker(myCall->callLock);
while (!myCall->callEnd)
myCall->callDone.wait(locker);
}
if (myCall->validPhone)
{
delete myCall;
return true;
}
delete myCall;
return false;
}
SipCall.h
SipCall(Account &acc, int call_id = PJSUA_INVALID_ID)
: Call(acc, call_id)
{
Acc = (SipAccount *)&acc;
this->callEnd = false;
this->validPhone = false;
}
~SipCall();
virtual void onCallState(OnCallStateParam &prm);
condition_variable callDone;
mutex callLock;
bool callEnd;
bool validPhone;
SipCall.cpp
void SipCall::onCallState(OnCallStateParam &prm)
{
PJ_UNUSED_ARG(prm);
CallInfo ci = getInfo();
std::cout << "*** Call: " << ci.remoteUri << " [" << ci.stateText
<< "]" << std::endl;
if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
{
unique_lock<mutex> locker(this->callLock);
this->callEnd = true;
this->callDone.notify_one();
}
}
if (ci.state == PJSIP_INV_STATE_CONFIRMED && ci.lastStatusCode == PJSIP_SC_OK)
{ //here i check that phone is valid, and just hang up the call
CallOpParam p;
this->validPhone = true;
this->hangup(p);
}
}
SipCall::~SipCall()
{
}
Since there a 3 lines avaliable im creating a three tasks to call the corresponding numbers like so:
QStringList testCalls; // initialized with numbers
struct call_result{
QString phone;
bool valid;
};
//....
QList<QFuture<call_result>> futureTestList;
while(counter < testCalls.count()) {
for(int i= 0; i < 3; i++,counter++) {
if(counter >= testCalls.count())
break;
QString number = testCalls.at(counter);
QFuture<call_result> futureResult = QtConcurrent::run(this,&sipQtThread::callNumber,number);
futureTestList.append(futureResult);
}
foreach(QFuture<call_result> future,futureTestList) {
future.waitForFinished();
call_result call = future.result();
emit phonePassed(call.phone,call.valid);
}
futureTestList.clear();
}
The correspondig task sipQtThread::callNumber is following:
sipQtThread::call_result sipQtThread::callNumber(QString phone)
{
call_result call;
pj_thread_desc initdec;
pj_thread_t* thread = 0;
pj_status_t status;
status = pj_thread_register(NULL, initdec, &thread);
if (status != PJ_SUCCESS) {
qDebug()<<"pj_thread_register faild:"<<status;
return call;
}
bool result = sip_->CallNumber(phone.toStdString());
call.phone = phone;
call.valid = result;
return call;
}
As you can see here
if (ci.state == PJSIP_INV_STATE_CONFIRMED && ci.lastStatusCode == PJSIP_SC_OK)
{ //here i check that phone is valid, and just hang up the call
CallOpParam p;
this->validPhone = true;
this->hangup(p);
}
I just check if the phone is valid, and call is starting, and the drop it. Can pjsua2 handle multiple line calls? Or even is pjsip supporting multiple outgoing lines calls? Does the thread registered by pj_thread_register needs to be somehow unregistered maybe?

Stack Corruption Warning in C++ using mysql C API prepared statement

I have a helper function for using prepared statements with mysql. All works well as long as i dont want to retrieve any results.
If i want to retrieve a result (e.g. simple long ID) im getting a warning from visual studio debugger that the stack is corrupted around my ID variable.
Header
bool RunPreparedStatement(std::string query, std::vector paramList, std::string& errbuf, int* affected_rows, bool fetchResultID = false, int32* result_id=0, bool fetchInsertID = false, int32* last_insert_id=0);
bool RunPreparedStatement(std::string sql, std::vector<MYSQL_BIND> paramList, std::string& errStr, int* affected_rows, bool fetchResultID, int32* result_id, bool fetchInsertID, int32* last_insert_id) {
char errbuf[MYSQL_ERRMSG_SIZE];
int numParams = paramList.size();
bool fetchResult = fetchResultID;
if(numParams == 0) {
errStr = "0 parameters supplied";
return false;
}
MYSQL_STMT *stmt = mysql_stmt_init(&mysql);
if (!stmt) {
errStr = "mysql_stmt_init(), out of memory";
return false;
}
if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length())) {
errStr = "mysql_stmt_prepare() failed ";
errStr.append(mysql_stmt_error(stmt));
return false;
}
int param_count= mysql_stmt_param_count(stmt);
if (param_count != numParams) /* validate parameter count */{
errStr = "invalid parameter count returned by MySQL";
return false;
}
if (mysql_stmt_bind_param(stmt, &paramList[0])) {
errStr = "mysql_stmt_bind_param() failed ";
errStr.append(mysql_stmt_error(stmt));
return false;
}
int32 id = 0;
MYSQL_BIND resultParam1;
BindValue(&resultParam1,MYSQL_TYPE_LONGLONG,&id,0,0,0);
if(fetchResult) {
/* Bind the results buffer */
if (mysql_stmt_bind_result(stmt, &resultParam1) != 0) {
errStr = "mysql_stmt_bind_result() failed ";
errStr.append(mysql_stmt_error(stmt));
return false;
}
}
if (mysql_stmt_execute(stmt)) {
errStr = "mysql_stmt_execute() failed ";
errStr.append(mysql_stmt_error(stmt));
return false;
}
if(fetchResult) {
if (mysql_stmt_store_result(stmt) != 0) {
errStr = "Could not buffer result set ";
errStr.append(mysql_stmt_error(stmt));
return false;
}
if(mysql_stmt_fetch (stmt) == 0) {
(*result_id) = id;
// OK
*affected_rows = 1;
} else {
*affected_rows = 0;
/*errStr = "no results found ";
errStr.append(mysql_stmt_error(stmt));
return false;*/
}
} else {
*affected_rows = mysql_stmt_affected_rows(stmt);
}
if(fetchInsertID) {
*last_insert_id= mysql_stmt_insert_id(stmt);
}
if(stmt != NULL) {
// Deallocate result set
mysql_stmt_free_result(stmt); /* deallocate result set */
if (mysql_stmt_close(stmt)) {
errStr = "closing the statement failed ";
errStr.append(mysql_stmt_error(stmt));
return false;
}
}
return true;
}
I call it like this
std::string errBuf;
int affected_rows = 0;
std::string sql = "SELECT count(*) FROM name WHERE (?) like name";
std::vector<MYSQL_BIND> paramList;
std::vector<MYSQL_BIND> resultParamList;
char data[1024];
safe_strncpy(data,name,sizeof(data), __FILE__, __LINE__);
MYSQL_BIND param1;
BindValue(&param1,MYSQL_TYPE_STRING,data,strlen(data),0,0);
paramList.push_back(param1);
int32 count = 0;
bool ret = true;
if(RunPreparedStatement(sql,paramList,errBuf,&affected_rows,true,&count)){
...
}
I previously had also a resultParamList instead of simple the ID and had the same error and thought it was related to return a list of values but that wasnt it.
Im receiving the warning as soon as the RunPreparedStatement method is finished.
Trying another sample code i found the issue
int32 id = 0;
MYSQL_BIND resultParam1;
BindValue(&resultParam1,MYSQL_TYPE_LONGLONG,&id,0,0,0);
im telling that the result type is MYSQL_TYPE_LONGLONG but im only giving it a int32 (unsigned int ) instead of unsigned long long.
So either change to MYSQL_TYPE_LONG or increase var size.