Невозможно убить поток Qt с CryptoPP FileSink, работающим в методе запуска потока

У меня есть приложение пользовательского интерфейса на C++ и QT5.4, я использую CryptoPP 5.6.2 для шифрования файлов. Я столкнулся со следующей проблемой:

  1. При нажатии кнопки «Зашифровать» запускается новый поток на основе это руководство.

    // new thread
    CryptoWorkerThread = new QThread;
    this->worker = new CryptoWorker(fileName.c_str(), newFileName.c_str(), key, keyLength, iv);
    this->worker->moveToThread(CryptoWorkerThread);
    connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
    connect(CryptoWorkerThread, SIGNAL(started()), worker, SLOT(process()));
    connect(worker, SIGNAL(finished()), CryptoWorkerThread, SLOT(quit()));
    connect(worker, SIGNAL(finished()), this, SLOT(on_CryptoWorker_finished()));
    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(CryptoWorkerThread, SIGNAL(finished()), CryptoWorkerThread, SLOT(deleteLater()));
    CryptoWorkerThread->start();
    
  2. Я храню указатель на поток и рабочий процесс в классе mainwindow (родитель кнопки шифрования и, следовательно, слот)

    Рабочий класс:

    class CryptoWorker : public QObject {
        Q_OBJECT
    public:
        CryptoWorker(const char* sourceFileName, const char* destFileName, const byte * key, int keyLength, const byte * iv);
        ~CryptoWorker();
    
        const char* sourceFileName;
        const char* destFileName;
    
        public slots:
        void process();
    
    signals:
        void finished();
        void error(QString err);
    
    private:
        // add your variables here
        const byte* key;
        const byte* iv;
        int keyLength;
    };
    
    CryptoWorker::CryptoWorker(const char* sourceFileName, const char* destFileName, const byte * key, int keyLength, const byte * iv){
        this->sourceFileName = sourceFileName;
        this->destFileName = destFileName;
        this->key = key;
        this->keyLength = keyLength;
        this->iv = iv;
    }
    
    CryptoWorker::~CryptoWorker(){
    
    }
    
    void CryptoWorker::process(){
    
        CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor(key, keyLength, iv);
    
    
        CryptoPP::FileSource(sourceFileName, true,
            new CryptoPP::StreamTransformationFilter(
                encryptor,
                new CryptoPP::FileSink(destFileName),
                CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING
            ),
            true // StreamTransformationFilter
        ); // FileSource
    
        emit finished();
    
        return;
    }
    

Теперь, когда поток запущен, и я шифрую файл A в файл B на лету, используя эту функцию:

CryptoPP::FileSource(sourceFileName, true,
        new CryptoPP::StreamTransformationFilter(
            encryptor,
            new CryptoPP::FileSink(destFileName),
            CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING
        ),
        true // StreamTransformationFilter
); // FileSource

Но поток зависает до тех пор, пока файл не завершит кодирование и запись, что может занять несколько минут. У меня нет возможности убить тред, так как негде поставить галочку isAlive().

Я пытаюсь найти решение, которое позволит мне использовать FileSource, FileSink (скорость по сравнению с fstream или file или qfile потрясающая), а также позволит мне отменить операцию в какой-то момент.

Я решил отслеживать прогресс, добавив еще один поток, который проверяет размер нового создаваемого зашифрованного файла B, но было бы здорово иметь контроль над байтами, которые записываются в данный момент (чтобы я мог проверять isAlive() и увеличивать счетчики данных ).

На данный момент я застрял и не могу найти решение. Пожалуйста помоги.


person michnovka    schedule 29.04.2015    source источник
comment
Хороший вопрос. @Yachour нашел для вас решение.   -  person jww    schedule 29.04.2015


Ответы (1)


Вы можете попробовать передать false второму параметру (pumpAll) конструктора FileSource и выполнить работу в цикле по частям, используя метод Pump - это должно позволить проверить isAlive и увеличить счетчики.

person yachoor    schedule 29.04.2015
comment
Ты подтолкнул меня на это. Я бы добавил к Pump исходя из размера блока диска, например, 4096 или 16 КБ. - person jww; 29.04.2015