From c016e4809df23ff5a7c9e8aee4826b1e3ecd5b20 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Wed, 22 Jul 2015 13:17:28 +0900 Subject: [PATCH] Fixed thread handling in KDict. This resolsed bug 1748. (cherry picked from commit 8942bd95385f6019a7ebfbeef7e1840412606be6) Signed-off-by: Michele Calgaro --- kdict/dict.cpp | 75 +++++++++++++++++++++++----------------------- kdict/dict.h | 19 ++++++------ kdict/toplevel.cpp | 7 +++++ 3 files changed, 54 insertions(+), 47 deletions(-) diff --git a/kdict/dict.cpp b/kdict/dict.cpp index 8094758d..6864cfe8 100644 --- a/kdict/dict.cpp +++ b/kdict/dict.cpp @@ -38,6 +38,7 @@ #include #include + //********* JobData ****************************************** @@ -53,8 +54,8 @@ JobData::JobData(QueryType Ntype,bool NnewServer,TQString const& Nserver,int Npo //********* DictAsyncClient ************************************* DictAsyncClient::DictAsyncClient(int NfdPipeIn, int NfdPipeOut) -: job(0L), inputSize(10000), fdPipeIn(NfdPipeIn), - fdPipeOut(NfdPipeOut), tcpSocket(-1), idleHold(0) +: TQThread(), job(0L), inputSize(10000), fdPipeIn(NfdPipeIn), + fdPipeOut(NfdPipeOut), tcpSocket(-1), idleHold(0), m_request_termination(false) { 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) { 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; - timeval tv; int selectRet; char buf; + timeval timeout_interval; - while (true) { + while (!m_request_termination) { if (tcpSocket != -1) { // we are connected, hold the connection for xx secs FD_ZERO(&fdsR); FD_SET(fdPipeIn, &fdsR); FD_SET(tcpSocket, &fdsR); FD_ZERO(&fdsE); FD_SET(tcpSocket, &fdsE); - tv.tv_sec = idleHold; - tv.tv_usec = 0; - selectRet = KSocks::self()->select(FD_SETSIZE, &fdsR, NULL, &fdsE, &tv); + int cnt = 0; + do { + 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 0)&&(!FD_ISSET(fdPipeIn,&fdsR)))||(selectRet == -1)) + if ((selectRet>0 && !FD_ISSET(fdPipeIn,&fdsR)) || selectRet==-1) closeSocket(); } } @@ -125,8 +116,13 @@ void DictAsyncClient::waitForWork() do { FD_ZERO(&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(); if (job) { @@ -785,7 +781,6 @@ void DictAsyncClient::openConnection() } KExtendedSocket ks; - ks.setAddress(job->server, job->port); ks.setTimeout(job->timeout); if (ks.connect() < 0) { @@ -1211,11 +1206,12 @@ DictInterface::DictInterface() (void) KSocks::self(); 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.")); kapp->exit(1); } - + client->start(); + jobList.setAutoDelete(true); } @@ -1223,13 +1219,16 @@ DictInterface::DictInterface() DictInterface::~DictInterface() { disconnect(notifier,TQT_SIGNAL(activated(int)),this,TQT_SLOT(clientDone())); - - if (0!=pthread_cancel(threadID)) - kdWarning() << "pthread_cancel failed!" << endl; - if (0!=pthread_join(threadID,NULL)) - kdWarning() << "pthread_join failed!" << endl; - delete client; - + if (client) + { + client->request_termination(); + if (!client->wait(3000)) + { + client->terminate(); + client->wait(3000); + } + } + if ( ::close( fdPipeIn[0] ) == -1 ) { perror( "Closing fdPipeIn[0]" ); } @@ -1242,6 +1241,8 @@ DictInterface::~DictInterface() if ( ::close( fdPipeOut[1] ) == -1 ) { perror( "Closing fdPipeOut[1]" ); } + + delete client; } diff --git a/kdict/dict.h b/kdict/dict.h index a4947c93..eb236fc2 100644 --- a/kdict/dict.h +++ b/kdict/dict.h @@ -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 - (C) by Matthias Hölzer 1998 + (C) by Matthias Hölzer 1998 This file is distributed under the Artistic License. See LICENSE for details. @@ -19,7 +19,7 @@ #ifndef _DICT_H_ #define _DICT_H_ -#include +#include #include #include @@ -95,22 +95,21 @@ public: //********* DictAsyncClient ****************************************** -class DictAsyncClient +class DictAsyncClient : public TQThread { - public: DictAsyncClient(int NfdPipeIn, int NfdPipeOut); ~DictAsyncClient(); - static void* startThread(void* pseudoThis); - + void run(); // main loop + void request_termination() { m_request_termination = true; } + void insertJob(JobData *newJob); void removeJob(); - + private: - void waitForWork(); // main loop void define(); bool getDefinitions(); bool match(); @@ -144,6 +143,7 @@ private: int fdPipeIn,fdPipeOut; //IPC-Pipes to/from async thread int tcpSocket,timeout,idleHold; TQTextCodec *codec; + bool m_request_termination; }; @@ -194,7 +194,6 @@ private: TQSocketNotifier *notifier; int fdPipeIn[2],fdPipeOut[2]; //IPC-Pipes to/from async thread - pthread_t threadID; DictAsyncClient *client; TQPtrList jobList; bool newServer,clientDoneInProgress; diff --git a/kdict/toplevel.cpp b/kdict/toplevel.cpp index 3ab47b05..46e4f02a 100644 --- a/kdict/toplevel.cpp +++ b/kdict/toplevel.cpp @@ -114,6 +114,12 @@ TopLevel::TopLevel(TQWidget* parent, const char* name) 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->hide(); delete splitter; + splitter=NULL; setCentralWidget(queryView); } else // list is not visible -> show it