I'm using Thrift 0.7.0 and am trying to get a C++ server up and running.
I'm able to run a simple server just fine with no issues, but when I try to
convert that server code to using the TNonblockingServer setup, the server
crashes.
I've used gdb to pinpoint the issue which occurs in
TConnection::workSocket() when it's trying to execute the ->read method:
// if we've already received some bytes we kept them here
framing.size = readWant_;
// determine size of this frame
try {
// Read from the socket
* fetch = tSocket_->read(&framing.buf[readBufferPos_],*
* uint32_t(sizeof(framing.size) -
readBufferPos_));*
Here's my run in gdb when I was trying to debug what was going on:
Starting program: /home/trevor/src/main/server/tservice/MyThriftService.dbg
[Thread debugging using libthread_db enabled]
[New Thread 0xb7539710 (LWP 3248)]
Thrift: Wed Jan 25 17:12:18 2012 libevent 1.4.13-stable method epoll
Breakpoint 1, apache::thrift::server::TConnection::workSocket
(this=0x87a4130) at src/server/TNonblockingServer.cpp:168
(gdb) stepi
0x00a2d73a 168 in src/server/TNonblockingServer.cpp
(gdb) stepi
0x00a2d73f 168 in src/server/TNonblockingServer.cpp
(gdb) stepi
0x00a2d741 168 in src/server/TNonblockingServer.cpp
(gdb) stepi
0x00a2d744 168 in src/server/TNonblockingServer.cpp
(gdb) stepi
0x00a2d746 168 in src/server/TNonblockingServer.cpp
(gdb) stepi
0x00a2d74a 168 in src/server/TNonblockingServer.cpp
(gdb) stepi
0x00a2d74e 168 in src/server/TNonblockingServer.cpp
(gdb) stepi
0x00a2d752 168 in src/server/TNonblockingServer.cpp
(gdb) stepi
0x0825e988 in vtable for __cxxabiv1::__si_class_type_info ()
(gdb) bt
#0 apache::thrift::server::TConnection::workSocket (this=0x84e2130) at
src/server/TNonblockingServer.cpp:168
#1 0x01055857 in apache::thrift::server::TConnection::eventHandler (fd=10,
v=0x84e2130) at src/server/TNonblockingServer.h:915
#2 0x0177d188 in event_base_loop () from /usr/lib/libevent-1.4.so.2
#3 0x0104f25f in apache::thrift::server::TNonblockingServer::serve
(this=0xbf892ff8) at src/server/TNonblockingServer.cpp:923
#4 0x08100eed in main (argc=-1081527784, argv=0x4e36e8c) at
MyThriftService.cpp:61
(gdb) p socketState_
$21 = apache::thrift::server::SOCKET_RECV_FRAMING
(gdb) p framing
$22 = {
buf = "\000\000\000",
size = 0
}
(gdb) p tSocket_
$23 = {
px = 0x84e2648,
pn = {
pi_ = 0x84e17f8
}
}
(gdb) p readBufferPos_
$24 = 0
(gdb) ptype *tSocket_.px
type = class apache::thrift::transport::TSocket : public
apache::thrift::transport::TVirtualTransport<apache::thrift::transport::TSocket,apache::thrift::transport::TTransportDefaults>
{
protected:
string host_;
string peerHost_;
string peerAddress_;
int peerPort_;
int port_;
string path_;
int socket_;
int connTimeout_;
int sendTimeout_;
int recvTimeout_;
bool lingerOn_;
int lingerVal_;
bool noDelay_;
int maxRecvRetries_;
timeval recvTimeval_;
apache::thrift::transport::TSocket::._97 cachedPeerAddr_;
timespec startTime_;
static bool useLowMinRto_;
public:
void TSocket(void);
void TSocket(string, int);
void TSocket(string);
void TSocket(int);
~TSocket(int);
virtual bool isOpen();
virtual bool peek();
virtual void open();
virtual void close();
uint32_t read(unsigned char*, unsigned int);
void write(unsigned char const*, unsigned int);
uint32_t write_partial(unsigned char const*, unsigned int);
string getHost();
int getPort();
void setHost(std::string);
void setPort(int);
void setLinger(bool, int);
void setNoDelay(bool);
void setConnTimeout(int);
void setRecvTimeout(int);
void setSendTimeout(int);
void setMaxRecvRetries(int);
string getSocketInfo();
string getPeerHost();
string getPeerAddress();
int getPeerPort();
int getSocketFD();
void setSocketFD(int);
sockaddr * getCachedAddress(unsigned int*) const;
static void setUseLowMinRto(bool);
static bool getUseLowMinRto();
void setCachedAddress(sockaddr const*, unsigned int);
protected:
void openConnection(addrinfo*);
private:
void unix_open();
void local_open();
}
(gdb) p readBufferPos_
$25 = 0
(gdb) bt
#0 0x0825e988 in vtable for __cxxabiv1::__si_class_type_info ()
#1 0x01050755 in apache::thrift::server::TConnection::workSocket
(this=0x84e2130) at src/server/TNonblockingServer.cpp:168
#2 0x01055857 in apache::thrift::server::TConnection::eventHandler (fd=10,
v=0x84e2130) at src/server/TNonblockingServer.h:915
#3 0x0177d188 in event_base_loop () from /usr/lib/libevent-1.4.so.2
#4 0x0104f25f in apache::thrift::server::TNonblockingServer::serve
(this=0xbf892ff8) at src/server/TNonblockingServer.cpp:923
#5 0x08100eed in main (argc=-1081527784, argv=0x4e36e8c) at
MyThriftService.cpp:61
(gdb) stepi
Program received signal SIGSEGV, Segmentation fault.
0x0825e988 in vtable for __cxxabiv1::__si_class_type_info ()
What could I possibly be missing? I've now tried to pear down my code to
the simplest version possible, but I'm still getting a segfault at this
point in the code. Any ideas? And again, when I use the simple server
implementation, the server runs just fine.
Any help is greatly appreciated. The server code is below.
Thanks,
Trevor
=======
// -- MyThriftServer.cpp
#include "thrift/Thrift.h"
#include "thrift/server.h"
#include "thrift/MyData.h"
#include "MyDataStore.h"
using boost::shared_ptr;
using namespace std;
class MyDataHandler : virtual public MyDataIf {
public:
MyDataHandler();
void GetEntries(std::vector<Entry> & _return, const std::string& user);
};
MyDataHandler::MyDataHandler() {
}
void MyDataHandler::GetEntries(vector<Entry> & _return, const string& user)
{
vector<string> entries = MyDataStore::getEntries(user);
for (size_t i = 0; i < entries.size(); i++) {
Entry e;
e.user = user;
e.record = entries[i];
e.__isset.record = true;
_return.push_back(e);
}
}
//-------------------------------------------
int main(int argc, char **argv) {
using namespace ::apache::thrift;
shared_ptr<MyDataHandler> handler(new MyDataHandler());
shared_ptr<TProcessor> processor(new MyDataProcessor(handler));
shared_ptr<protocol::TProtocolFactory> protocolFactory(new
protocol::TBinaryProtocolFactory());
// using thread pool with maximum 15 threads to handle incoming requests
// shared_ptr<concurrency::ThreadManager> threadManager =
concurrency::ThreadManager::newSimpleThreadManager(15);
// shared_ptr<concurrency::PosixThreadFactory> threadFactory =
shared_ptr<concurrency::PosixThreadFactory>(new
concurrency::PosixThreadFactory());
// threadManager->threadFactory(threadFactory);
// threadManager->start();
server::TNonblockingServer server(processor, protocolFactory, 14341);
server.serve();
return 0;
}