I have a small program that tries to connect to mongodb and check how many objects it would receive if I could hope to receive objects. In the event, I can't even get a count of objects, and I segfault on cleanup even if I do nothing but connect.
I'm using the GlobalInstance object to maintain my connection and clean up for me at exit. This function I call from main. The program doesn't really do anything else yet.
Any suggestions on what I'm doing wrong that I segfault? Presumably this is related to not being able to call connection->count()?
Many thanks for any pointers.
int foo() {
mongo::client::Options options;
options.setSSLMode(mongo::client::Options::kSSLRequired);
mongo::client::GlobalInstance mongo_connection(options);
mongo::DBClientBase* connection;
if (!mongo_connection.status().isOK()) {
cout << "Mongo connection not established: "
<< mongo_connection.status() << endl;
}
try {
mongo::DBClientConnection c(true);
string error;
ostringstream mongo_url;
mongo_url << "mongodb://" << db_username << ":" << db_password << "#"
<< db_host << ":" << db_port << "/" << db_name;
const mongo::ConnectionString conn_string =
mongo::ConnectionString::parse(mongo_url.str(), error);
if (!conn_string.isValid()) {
cout << "Bad connection string: " << error << endl;
}
// Reality check. Passes.
cout << "user=" << conn_string.getUser() << endl;
cout << "pass=" << conn_string.getPassword() << endl;
cout << "db= " << conn_string.getDatabase() << endl;
const auto servers = conn_string.getServers();
for (const auto& server : servers) {
cout << "serv=" << server << endl;
}
cout << "type=" << conn_string.type() << endl;
// End reality check.
connection = conn_string.connect(error);
cout << "error says: " << error << endl; // Is empty.
cout << "conn=" << connection << endl; // Not zero.
std::cout << "connected ok" << std::endl;
cout << connection->getConnectionId() << endl; // Prints "1".
// This returns an error 13, not authorized, if I included it.
//cout << "count: " << connection->count("focus_groups") << endl;
} catch( const mongo::DBException &e ) {
std::cout << "caught " << e.what() << std::endl;
}
cout << "----------------------------------------------------------------------" << endl;
return 0;
}
/*
Note that I can do this in the mongo shell with no problem:
jeff#siegfried:~ $ mongo my_host:27017/my_db --ssl -u my_user -p
MongoDB shell version: 2.6.3
Enter password:
connecting to: my_host:27017/my_db
> db.focus_groups.count()
26
>
*/
I am running on 64 bit ubuntu 15.04 and compiling with clang 3.6.0. Boost is 1.55 installed via apt-get. The legacy mongo C++ driver I compiled and installed from git at HEAD (861699d116627d63e1c914384a66e4e3ea7c23bc) with ssl support.
This turned out to be a confluence of several things, but at least these two:
When I compiled the legacy driver, the default mode is C++03, which is not binary compatible with C++11 or C++14.
The driver is sensitive to differences in the version of boost with which it and the client using it are compiled.
An extensive thread appears here.
Related
In working with the zmq library in C/C++, the following code produces a segmentation fault on the bind command. Using ZMQ v4.2.5 (currently the latest stable release). Below is the relevant code for the connection: creating the context, the socket, and binding the socket (which is the trouble line).
cout << "Creating the context" << endl;
void* ctx = zmq_ctx_new();
if (ctx == NULL)
{
cout << "Context was null!" << endl;
cout << "ZMQ Error code: " << zmq_strerror(zmq_errno()) << endl;
return -1;
}
else cout << "Address of the context: " << ctx << endl;
cout << "Creating the socket now" << endl;
void* socket = zmq_socket(ctx, ZMQ_DEALER);
if (socket == NULL)
{
cout << "Socket was null!" << endl;
cout << "ZMQ Error code: " << zmq_strerror(zmq_errno()) << endl;
return -1;
}
else cout << "Socket created! Address of the socket: " << socket << endl;
const char[] addr = "ipc://test";
cout << "Binding the socket now: " << addr << endl;
int rc = zmq_bind(socket, addr); // <-- SegFault Line
if (rc != 0)
{
cout << "ERROR BINDING THE SOCKET!" << endl;
cout << "ZMQ Error code: " << zmq_strerror(zmq_errno()) << endl;
return -1;
}
else cout << "Socket successfully bound" << endl;
Additional information:
binding the socket works with inproc, but causes the segmentation fault with ipc or tcp
user has appropriate permissions to write to the folder (for ipc sockets)
Valgrind returns a bad permissions for mapped region error in the zmq code pointing at the set_address function
Error still persists if passing in literal string as the argument (as opposed to addr variable)
Running on Centos 7.5 with KDE
Thank you for your time.
Edit: Added OS information in the Additional Information section
By attempting to access the TCPSocket inside my "clientArray" I get a Access Violation error. How would I access it properly?
My header file holds the TCPSocket *clientArray.
public:
TCPsocket *clientArray;
SDLNet_SocketSet aSocketSet;
bool serverOn;
It is defined within my constructor:
clientArray = new TCPsocket[maxsockets];
aSocketSet = SDLNet_AllocSocketSet(maxsockets);
It is accessible within another function of mine (it works here without issue):
void ServerSocket::waitingForConnection() {
std::cout << '\r' << flush << "Players connected: " << playersConnected << ". Listening for connection... ";
TCPsocket newsocket = SDLNet_TCP_Accept(serverSocket);
SDL_Delay(1000);
if (!newsocket){
//std::cout << '\r' << flush << "Listening for connection. ";
//std::cout << SDLNet_GetError() << std::endl;
}
else{
std::cout << '\r' << flush << "Socket (client " << slotnum + 1 << ") created successfully. " << std::endl;
clientArray[slotnum] = newsocket;
int n = SDLNet_TCP_AddSocket(aSocketSet, newsocket);
if (n < 0){
std::cout << "Client " << slotnum + 1 << " failed to connect. " << std::endl;
}
else{
char text[10];
std::cout << "Client " << slotnum + 1 << " added to client array successfully." << std::endl;
serverMessage(slotnum, "2 You are successfully connected to the server.");
std::cout << "Sent connection validation to Client " << slotnum + 1 << "." << endl;
std::cout << "Allocating player " << slotnum + 1 << " with player number ." << endl;
serverData(slotnum, '5', slotnum+1);
//ACCESSING IT HERE WITHOUT ISSUE
SDLNet_TCP_Recv(clientArray[slotnum], text, 10);
std::cout << "received text = " << text << endl;
interpretData(text);
slotnum++;
}
//SDLNet_TCP_Close(newsocket);
//SDLNet_TCP_Close(serverSocket);
//code here
}
}
However later on when I try to access it via another function, I get an Access Violation Error :
Unhandled exception at 0x00AED839 in Server.exe: 0xC0000005: Access violation reading location 0x0000000C.
I am calling the problematic function from my Game's Update function as following:
void Game::Update(){
while (g_playersConnected == 2)
{
printGrid();
serverSocket->waitForPlayer((playerTurn-1));
changeTurn();
system("pause");
}
//cout << "Game's Update is running" << endl;
};
This is my other function that is attempting to access the array :
void ServerSocket::waitForPlayer(int playerNum)
{
cout << "Waiting for player " << playerNum + 1 << " (In array : " << playerNum << ")." << endl;
char text[10];
SDLNet_TCP_Recv(clientArray[playerNum], text, 10);
std::cout << "received text = " << text << endl;
interpretData(text);
}
I have not set up Copy constructors or assignment operators and my destructors are just empty blocks at the moment.
ServerSocket::~ServerSocket(){}
Which direction should I go towards solving this issue?
All the best
I am trying to get a bigint value (named "NUM" in my example) that comes from my database (Microsoft SQL Server). In the following code, I am trying to get it as an int even if I know that an int is smaller than a bigint but the cast always fails. I also tried to get it as a long long int and as some other types of variable but I am always getting the same problem at runtime as shown below.
try
{
session sql(odbc, "...");
rowset<row> rs = (sql.prepare << "SELECT MAX(NUM) AS MAX_NUM FROM T1");
for (rowset<row>::const_iterator it = rs.begin(); it != rs.end(); ++it)
{
row const& row = *it;
cout << "MAX_NUM: " << row.get<int>("MAX_NUM") << endl;
}
}
catch (exception const &e)
{
cerr << "Error: " << e.what() << '\n';
}
I have also tried the following getters:
cout << "MAX_NUM: " << row.get<long>("MAX_NUM") << endl;
cout << "MAX_NUM: " << row.get<long long>("MAX_NUM") << endl;
cout << "MAX_NUM: " << row.get<long long int>("MAX_NUM") << endl;
All my tests print the same error when I run my application:
Error: std::bad_cast
My question is : What is the correct way to get this value ?
I don't know if it is the best solution but it is the only one I found that works:
cout << "MAX_NUM: " << row.get<double>("MAX_NUM") << endl;
I have a piece of code, quite basic, for logging in into an xmpp server in libjingle.
I cannot log in into the server. I am sure that the parameters are correct since I checked with an xmpp client program.
My sequence is like this:
Create XmppPump.
Setup callback for xmppPump.client().SignalStateChange, which should be called when progress is done through the different states in XmppEngine.
Start the signaling thread and block on a future that will be unblocked when XmppPump::DoLogin is done.
buzz::XmppClient * xmppClient = mI->xmppPump.client();
assert(xmppClient != nullptr);
buzz::Jid jid = buzz::Jid(user);
std::string server = serverHost + ":" +
std::to_string(kXmppClientDefaultPort);
bool allow_plain = true;
buzz::XmppClientSettings xcs;
xcs.set_user(jid.node());
xcs.set_resource(jid.resource());
xcs.set_host(jid.domain());
xcs.set_allow_plain(allow_plain);
xcs.set_use_tls(buzz::TLS_DISABLED);
talk_base::InsecureCryptStringImpl pass;
pass.password() = password;
xcs.set_pass(talk_base::CryptString(pass));
std::string server_;
int port;
std::size_t colon = server.find(':');
if (colon == std::string::npos) {
server_ = server;
port = kXmppClientDefaultPort;
}
else {
server_ = server.substr(0, colon);
port = atoi(server.substr(colon + 1).c_str());
}
std::cout << "Logging in as user " << jid.node() << std::endl;
std::cout << "User domain is " << jid.domain() << std::endl;
std::cout << "Resource is " << jid.resource() << std::endl;
std::cout << "Password is " << password << std::endl;
std::cout << "Logging into server " << server_;
std::cout << " port " << port << std::endl;
xcs.set_server(talk_base::SocketAddress(server_, port));
xcs.set_protocol(cricket::PROTO_SSLTCP);
talk_base::InitializeSSL();
std::future<buzz::XmppEngine::State> result =
mI->xmppLoginState.get_future();
//Callback is setup here
xmppClient->SignalStateChange.connect(mI.get(),
&Impl::OnStateChange);
std::cout << std::endl;
std::cout << "About to call buzz::XmppPump::DoLogin " << std::endl;
//Logging in async.
mI->xmppPump.DoLogin(xcs, new buzz::XmppSocket(buzz::TLS_DISABLED), nullptr);
std::cout << "Called buzz::XmppPump::DoLogin " << std::endl;
mI->signalingThread.Start();
std::cout << "Blocked waiting for buzz::xmppPump::DoLogin to finish."
<< std::endl;
//Forever here and XmppEngine::STATE_STARTED always.
result.get();
std::cout << "buzz::XmppPump::DoLogin finished.";
I'm tryning to build a service con gsoap. The code is:
ArchivatorCoreService server;
ArchivatorCoreService *tserver;
int port = 8080;
SOAP_SOCKET m, s;
m = server.bind(NULL, port, 100);
if (!soap_valid_socket(m))
{
exit(1);
}
else
{
qDebug() << "Info: Bind: Succesfully socket connection: " << m << ". Port " << port
}
for (;;)
{
qDebug() << "waiting...";
s = server.accept();
if (!soap_valid_socket(s))
{
if (server.errnum)
{
qDebug() << "1"; << "Error: Failed accept: " << messagec;
exit(1);
}
else
{
qDebug() << "Info: Thread " << i << " accepts socket " << s << " connection from IP " << ((server.ip >> 24)&0xFF) << "." << ((server.ip >> 16)&0xFF) << "." << ((server.ip >> 8)&0xFF) << "." << ((server.ip)&0xFF);
}
qDebug() << "2";
tserver = server.copy(); // make a safe copy
qDebug() << "3";
In line tserver = server.copy(); error sigsegv.
ArchivatorCoreService heracly of soap;
Thanks you very much
You don't say which version of gsoap you are using; however versions prior to 2.8.5 have an issue with memory leaks and SIGSEGVs with the C++ code that is generated. See my previous answer here for a few more details.