[Network] and [Kernal] add cancel from thread (linux)

This commit is contained in:
Vladimir Gorshenkov
2022-01-22 14:55:28 +03:00
parent 7066a55813
commit 920adde65f
7 changed files with 105 additions and 20 deletions

View File

@ -56,6 +56,8 @@ namespace NSNetwork
virtual void Suspend() = 0;
virtual void Resume() = 0;
virtual void Stop() = 0;
virtual void StopNoJoin() = 0;
virtual void Cancel() = 0;
virtual int IsRunned() = 0;
//events
@ -92,6 +94,8 @@ namespace NSNetwork
virtual void Suspend();
virtual void Resume();
virtual void Stop();
virtual void StopNoJoin();
virtual void Cancel();
virtual int IsRunned();
virtual void SetEvent_OnProgress(std::function<void(int)>);
virtual void SetEvent_OnComplete(std::function<void(int)>);
@ -122,6 +126,8 @@ namespace NSNetwork
virtual void Suspend();
virtual void Resume();
virtual void Stop();
virtual void StopNoJoin();
virtual void Cancel();
virtual int IsRunned();
virtual void SetEvent_OnProgress(std::function<void(int)>);
virtual void SetEvent_OnComplete(std::function<void(int)>);

View File

@ -101,6 +101,8 @@ namespace NSNetwork
void CFileDownloader::Suspend() { m_pInternal->Suspend(); }
void CFileDownloader::Resume() { m_pInternal->Resume(); }
void CFileDownloader::Stop() { m_pInternal->Stop(); }
void CFileDownloader::StopNoJoin() { m_pInternal->StopNoJoin(); }
void CFileDownloader::Cancel() { m_pInternal->Cancel(); }
int CFileDownloader::IsRunned() { return m_pInternal->IsRunned(); }
void CFileDownloader::SetEvent_OnProgress(std::function<void(int)> func)
@ -164,6 +166,8 @@ namespace NSNetwork
void CFileUploader::Suspend() { m_pInternal->Suspend(); }
void CFileUploader::Resume() { m_pInternal->Resume(); }
void CFileUploader::Stop() { m_pInternal->Stop(); }
void CFileUploader::StopNoJoin() { m_pInternal->StopNoJoin(); }
void CFileUploader::Cancel() { m_pInternal->Cancel(); }
int CFileUploader::IsRunned() { return m_pInternal->IsRunned(); }
void CFileUploader::SetEvent_OnProgress(std::function<void(int)> func)

View File

@ -241,7 +241,7 @@ namespace NSNetwork
if (NSFile::CFileBinary::Exists(m_sDownloadFilePath))
NSFile::CFileBinary::Remove(m_sDownloadFilePath);
}
return download_external(m_sDownloadFileUrl, m_sDownloadFilePath, m_func_onProgress);
return download_external(m_sDownloadFileUrl, m_sDownloadFilePath, m_func_onProgress, m_bIsExit);
}
virtual int UploadData() override
{

View File

@ -61,6 +61,8 @@ namespace NSNetwork
m_func_onComplete = NULL;
m_func_onProgress = NULL;
m_bIsExit = nullptr;
}
CFileTransporterBase(const std::wstring &sUploadUrl, const unsigned char* cData, const int nSize)
@ -82,6 +84,8 @@ namespace NSNetwork
m_func_onComplete = NULL;
m_func_onProgress = NULL;
m_bIsExit = nullptr;
}
CFileTransporterBase(const std::wstring &sUploadUrl, const std::wstring &sUploadFilePath)
@ -103,6 +107,8 @@ namespace NSNetwork
m_func_onComplete = NULL;
m_func_onProgress = NULL;
m_bIsExit = nullptr;
}
virtual ~CFileTransporterBase ()
@ -143,6 +149,8 @@ namespace NSNetwork
std::function<void(int)> m_func_onComplete;
std::function<void(int)> m_func_onProgress;
std::atomic<bool>* m_bIsExit; // Для остановки и выхода потока
};
class CFileTransporter_private : public NSThreads::CBaseThread
@ -234,6 +242,7 @@ namespace NSNetwork
virtual DWORD ThreadProc ()
{
m_pInternal->m_bComplete = false;
m_pInternal->m_bIsExit = NSThreads::CBaseThread::m_bIsExit;
int hrResultAll = 0;
if(m_pInternal->m_eLoadType == m_pInternal->DOWNLOADFILE)
@ -245,6 +254,11 @@ namespace NSNetwork
if (0 == hrResultAll)
m_pInternal->m_bComplete = true;
else
{
if (NSFile::CFileBinary::Exists(m_pInternal->m_sDownloadFilePath))
NSFile::CFileBinary::Remove(m_pInternal->m_sDownloadFilePath);
}
if (m_pInternal->m_func_onComplete)
m_pInternal->m_func_onComplete(hrResultAll);

View File

@ -41,11 +41,14 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <regex>
#include <atomic>
namespace NSNetwork
{
namespace NSFileTransport
{
pid_t pid;
std::atomic<bool>* m_isExit;
std::string wget_url_validate(const std::string& url)
{
std::string::size_type pos = 0;
@ -58,9 +61,10 @@ namespace NSNetwork
return url.substr(pos);
}
int download_external(const std::wstring& sUrl, const std::wstring& sOutput, std::function<void(int)> func_onProgress)
int download_external(const std::wstring& sUrl, const std::wstring& sOutput, std::function<void(int)> func_onProgress, std::atomic<bool>* isExit)
{
int nReturnCode = -1;
m_isExit = isExit;
std::string sUrlA = U_TO_UTF8(sUrl);
//sUrlA =("\"" + sUrlA + "\"");
std::string sOutputA = U_TO_UTF8(sOutput);
@ -72,7 +76,7 @@ namespace NSNetwork
if(func_onProgress)
pipe(pipefd);
pid_t pid = fork(); // create child process
pid = fork(); // create child process
int status;
switch (pid)
@ -116,13 +120,27 @@ namespace NSNetwork
default: // parent process, pid now contains the child pid
if(func_onProgress)
{
close(pipefd[1]);
// close the write end of the pipe in the parent
size_t size = 81;
char buffer[size];
std::string str;
close(pipefd[1]); // close the write end of the pipe in the parent
ssize_t res = 1;
std::regex r(R"(\d+(?:\.\d+)?%)");
std::smatch sm;
std::string percentFull;
std::string percent;
int percentInt;
while (1)
{
if(m_isExit->load())
{
kill(pid, SIGTERM);
//while (-1 == waitpid(pid, &status, 0)); // wait for child to complete
return nReturnCode;
}
str.clear();
res = read(pipefd[0], buffer, sizeof(buffer));
@ -131,15 +149,11 @@ namespace NSNetwork
str.append(buffer);
std::regex r(R"(\d+(?:\.\d+)?%)");
std::smatch sm;
std::string percentFull;
std::string percent;
if(regex_search(str, sm, r))
{
percentFull = sm.str();
percent = percentFull.substr(0, percentFull.find("."));
int percentInt = std::stoi(percent);
percentInt = std::stoi(percent);
if(percentInt >= 0 && percentInt <= 100)
func_onProgress(percentInt);
@ -147,14 +161,28 @@ namespace NSNetwork
if(str.find("100.0%") != std::string::npos)
break;
}
}
while (-1 == waitpid(pid, &status, 0)); // wait for child to complete
if (WIFEXITED(status))
{
nReturnCode = WEXITSTATUS(status);
else {
int waitres;
while (1) // wait for child to complete
{
if(m_isExit->load())
{
kill(pid, SIGTERM);
return nReturnCode;
}
else if((waitres = waitpid(pid, &status, WNOHANG)) > 0)
{
if (WIFEXITED(status))
{
nReturnCode = WEXITSTATUS(status);
}
break;
}
}
}
break;
}
}
@ -162,7 +190,7 @@ namespace NSNetwork
{
std::string sUrlValidateA = wget_url_validate(sUrlA);
pid_t pid = fork(); // create child process
pid = fork(); // create child process
int status;
switch (pid)
@ -191,12 +219,23 @@ namespace NSNetwork
break;
}
default: // parent process, pid now contains the child pid
while (-1 == waitpid(pid, &status, 0)); // wait for child to complete
if (WIFEXITED(status))
int waitres;
while (1) // wait for child to complete
{
nReturnCode = WEXITSTATUS(status);
if(m_isExit->load())
{
kill(pid, SIGTERM);
return nReturnCode;
}
else if((waitres = waitpid(pid, &status, WNOHANG)) > 0)
{
if (WIFEXITED(status))
{
nReturnCode = WEXITSTATUS(status);
}
break;
}
}
break;
}
}