Fixed thread handling in KDict. This resolsed bug 1748.

(cherry picked from commit 8942bd9538)
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
pull/38/head
Michele Calgaro 9 years ago
parent 1da54d8c25
commit c016e4809d

@ -38,6 +38,7 @@
#include <signal.h> #include <signal.h>
#include <stdlib.h> #include <stdlib.h>
//********* JobData ****************************************** //********* JobData ******************************************
@ -53,8 +54,8 @@ JobData::JobData(QueryType Ntype,bool NnewServer,TQString const& Nserver,int Npo
//********* DictAsyncClient ************************************* //********* DictAsyncClient *************************************
DictAsyncClient::DictAsyncClient(int NfdPipeIn, int NfdPipeOut) DictAsyncClient::DictAsyncClient(int NfdPipeIn, int NfdPipeOut)
: job(0L), inputSize(10000), fdPipeIn(NfdPipeIn), : TQThread(), job(0L), inputSize(10000), fdPipeIn(NfdPipeIn),
fdPipeOut(NfdPipeOut), tcpSocket(-1), idleHold(0) fdPipeOut(NfdPipeOut), tcpSocket(-1), idleHold(0), m_request_termination(false)
{ {
input = new char[inputSize]; input = new char[inputSize];
} }
@ -68,22 +69,6 @@ DictAsyncClient::~DictAsyncClient()
} }
void* DictAsyncClient::startThread(void* pseudoThis)
{
DictAsyncClient* newthis = (DictAsyncClient*) (pseudoThis);
if (0!=pthread_setcanceltype(PTHREAD_CANCEL_ENABLE,NULL))
tqWarning("pthread_setcanceltype failed!");
if (0!= pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL))
tqWarning("pthread_setcanceltype failed!");
signal(SIGPIPE,SIG_IGN); // ignore sigpipe
newthis->waitForWork();
return NULL;
}
void DictAsyncClient::insertJob(JobData *newJob) void DictAsyncClient::insertJob(JobData *newJob)
{ {
if (!job) // don't overwrite existing job pointer if (!job) // don't overwrite existing job pointer
@ -97,27 +82,33 @@ void DictAsyncClient::removeJob()
} }
void DictAsyncClient::waitForWork() void DictAsyncClient::run()
{ {
fd_set fdsR,fdsE; fd_set fdsR,fdsE;
timeval tv;
int selectRet; int selectRet;
char buf; char buf;
timeval timeout_interval;
while (true) { while (!m_request_termination) {
if (tcpSocket != -1) { // we are connected, hold the connection for xx secs if (tcpSocket != -1) { // we are connected, hold the connection for xx secs
FD_ZERO(&fdsR); FD_ZERO(&fdsR);
FD_SET(fdPipeIn, &fdsR); FD_SET(fdPipeIn, &fdsR);
FD_SET(tcpSocket, &fdsR); FD_SET(tcpSocket, &fdsR);
FD_ZERO(&fdsE); FD_ZERO(&fdsE);
FD_SET(tcpSocket, &fdsE); FD_SET(tcpSocket, &fdsE);
tv.tv_sec = idleHold; int cnt = 0;
tv.tv_usec = 0; do {
selectRet = KSocks::self()->select(FD_SETSIZE, &fdsR, NULL, &fdsE, &tv); FD_ZERO(&fdsR);
FD_SET(fdPipeIn, &fdsR);
++cnt;
timeout_interval.tv_sec=1;
timeout_interval.tv_usec=0;
selectRet=KSocks::self()->select(FD_SETSIZE, &fdsR, NULL, &fdsE, &timeout_interval);
} while (!m_request_termination && cnt<idleHold && selectRet==0);
if (selectRet == 0) { if (selectRet == 0) {
doQuit(); // nothing happend... doQuit(); // nothing happend...
} else { } else {
if (((selectRet > 0)&&(!FD_ISSET(fdPipeIn,&fdsR)))||(selectRet == -1)) if ((selectRet>0 && !FD_ISSET(fdPipeIn,&fdsR)) || selectRet==-1)
closeSocket(); closeSocket();
} }
} }
@ -125,8 +116,13 @@ void DictAsyncClient::waitForWork()
do { do {
FD_ZERO(&fdsR); FD_ZERO(&fdsR);
FD_SET(fdPipeIn, &fdsR); FD_SET(fdPipeIn, &fdsR);
} while (select(FD_SETSIZE, &fdsR, NULL, NULL, NULL)<0); // don't get tricked by signals timeout_interval.tv_sec=1;
timeout_interval.tv_usec=0;
} while (!m_request_termination && select(FD_SETSIZE, &fdsR, NULL, NULL, &timeout_interval)<=0);
if (m_request_termination)
return;
clearPipe(); clearPipe();
if (job) { if (job) {
@ -785,7 +781,6 @@ void DictAsyncClient::openConnection()
} }
KExtendedSocket ks; KExtendedSocket ks;
ks.setAddress(job->server, job->port); ks.setAddress(job->server, job->port);
ks.setTimeout(job->timeout); ks.setTimeout(job->timeout);
if (ks.connect() < 0) { if (ks.connect() < 0) {
@ -1211,11 +1206,12 @@ DictInterface::DictInterface()
(void) KSocks::self(); (void) KSocks::self();
client = new DictAsyncClient(fdPipeOut[0],fdPipeIn[1]); client = new DictAsyncClient(fdPipeOut[0],fdPipeIn[1]);
if (0!=pthread_create(&threadID,0,&(client->startThread),client)) { if (!client) {
KMessageBox::error(global->topLevel, i18n("Internal error:\nUnable to create thread.")); KMessageBox::error(global->topLevel, i18n("Internal error:\nUnable to create thread."));
kapp->exit(1); kapp->exit(1);
} }
client->start();
jobList.setAutoDelete(true); jobList.setAutoDelete(true);
} }
@ -1223,13 +1219,16 @@ DictInterface::DictInterface()
DictInterface::~DictInterface() DictInterface::~DictInterface()
{ {
disconnect(notifier,TQT_SIGNAL(activated(int)),this,TQT_SLOT(clientDone())); disconnect(notifier,TQT_SIGNAL(activated(int)),this,TQT_SLOT(clientDone()));
if (client)
if (0!=pthread_cancel(threadID)) {
kdWarning() << "pthread_cancel failed!" << endl; client->request_termination();
if (0!=pthread_join(threadID,NULL)) if (!client->wait(3000))
kdWarning() << "pthread_join failed!" << endl; {
delete client; client->terminate();
client->wait(3000);
}
}
if ( ::close( fdPipeIn[0] ) == -1 ) { if ( ::close( fdPipeIn[0] ) == -1 ) {
perror( "Closing fdPipeIn[0]" ); perror( "Closing fdPipeIn[0]" );
} }
@ -1242,6 +1241,8 @@ DictInterface::~DictInterface()
if ( ::close( fdPipeOut[1] ) == -1 ) { if ( ::close( fdPipeOut[1] ) == -1 ) {
perror( "Closing fdPipeOut[1]" ); perror( "Closing fdPipeOut[1]" );
} }
delete client;
} }

@ -1,9 +1,9 @@
/* ------------------------------------------------------------- /* -------------------------------------------------------------
dict.h (part of The KDE Dictionary Client) dict.h (part of The TDE Dictionary Client)
Copyright (C) 2000-2001 Christian Gebauer <gebauer@kde.org> Copyright (C) 2000-2001 Christian Gebauer <gebauer@kde.org>
(C) by Matthias Hölzer 1998 (C) by Matthias Hölzer 1998
This file is distributed under the Artistic License. This file is distributed under the Artistic License.
See LICENSE for details. See LICENSE for details.
@ -19,7 +19,7 @@
#ifndef _DICT_H_ #ifndef _DICT_H_
#define _DICT_H_ #define _DICT_H_
#include <pthread.h> #include <ntqthread.h>
#include <tqptrlist.h> #include <tqptrlist.h>
#include <tqsocketnotifier.h> #include <tqsocketnotifier.h>
@ -95,22 +95,21 @@ public:
//********* DictAsyncClient ****************************************** //********* DictAsyncClient ******************************************
class DictAsyncClient class DictAsyncClient : public TQThread
{ {
public: public:
DictAsyncClient(int NfdPipeIn, int NfdPipeOut); DictAsyncClient(int NfdPipeIn, int NfdPipeOut);
~DictAsyncClient(); ~DictAsyncClient();
static void* startThread(void* pseudoThis); void run(); // main loop
void request_termination() { m_request_termination = true; }
void insertJob(JobData *newJob); void insertJob(JobData *newJob);
void removeJob(); void removeJob();
private: private:
void waitForWork(); // main loop
void define(); void define();
bool getDefinitions(); bool getDefinitions();
bool match(); bool match();
@ -144,6 +143,7 @@ private:
int fdPipeIn,fdPipeOut; //IPC-Pipes to/from async thread int fdPipeIn,fdPipeOut; //IPC-Pipes to/from async thread
int tcpSocket,timeout,idleHold; int tcpSocket,timeout,idleHold;
TQTextCodec *codec; TQTextCodec *codec;
bool m_request_termination;
}; };
@ -194,7 +194,6 @@ private:
TQSocketNotifier *notifier; TQSocketNotifier *notifier;
int fdPipeIn[2],fdPipeOut[2]; //IPC-Pipes to/from async thread int fdPipeIn[2],fdPipeOut[2]; //IPC-Pipes to/from async thread
pthread_t threadID;
DictAsyncClient *client; DictAsyncClient *client;
TQPtrList<JobData> jobList; TQPtrList<JobData> jobList;
bool newServer,clientDoneInProgress; bool newServer,clientDoneInProgress;

@ -114,6 +114,12 @@ TopLevel::TopLevel(TQWidget* parent, const char* name)
TopLevel::~TopLevel() TopLevel::~TopLevel()
{ {
if (splitter)
delete splitter;
if (interface)
delete interface;
if (global)
delete global;
} }
@ -636,6 +642,7 @@ void TopLevel::toggleMatchListShow()
matchView->reparent(this,0,matchView->pos(),true); matchView->reparent(this,0,matchView->pos(),true);
matchView->hide(); matchView->hide();
delete splitter; delete splitter;
splitter=NULL;
setCentralWidget(queryView); setCentralWidget(queryView);
} }
else // list is not visible -> show it else // list is not visible -> show it

Loading…
Cancel
Save