Проблема с эхом в консольном приложении (Linux) - PullRequest
3 голосов
/ 21 июля 2009

У меня странная проблема в консольном приложении.

Прежде всего, фрагмент кода:

main.cpp

#include "DebugInterface.h"

static sigset_t signalSet;
static pthread_t CleanupHandlerThread;
DebugInterface* debugInterface = NULL;

void* CleanupHandler (void* param) {
    int32_t sig, err;
    err = sigwait (&signalSet, &sig);

    delete debugInterface;
    debugInterface = NULL;
    exit (EXIT_SUCCESS);

    return NULL;
}

int32_t main(int32_t argc, char** argv) {
    sigemptyset (&signalSet);
    sigaddset (&signalSet, SIGINT);
    pthread_sigmask (SIG_BLOCK, &signalSet, NULL);
    pthread_create (&CleanupHandlerThread, NULL, CleanupHandler, NULL);

    debugInterface = new DebugInterface();

    if (debugInterface != NULL) {
        debugInterface->StartReading();
    }

    while (true) {
        // Core functionality follows, but was commented out
        // (was not relevant for problem, checked it -
        // you may even remove this loop completely)
    }

    return EXIT_SUCCESS;
}

DebugInterface.h

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <iomanip>
#include <readline/readline.h>
#include <readline/history.h>
#include <signal.h>

class DebugInterface {
public:
    DebugInterface() { }
    virtual ~DebugInterface() { }

private:
    pthread_t ConsoleHandlerThread;

private:
    static void* ConsoleHandler (void* param);

public:
    bool StartReading();
};

DebugInterface.cpp

#include "DebugInterface.h"

void* DebugInterface::ConsoleHandler (void* param) {
    while (true) {
        char* input = readline ("\n> ");

        // Handle input, was commented out, too (irrelevant for problem)

        free (input);
    }

    return NULL;
}

bool DebugInterface::StartReading() {
    if (pthread_create (&ConsoleHandlerThread, NULL, DebugInterface::ConsoleHandler, NULL) != 0) {
        return false;
    }
    return true;
}

Код работает нормально и, как и ожидалось, но когда он выходит и завершается, перехватывая сигнал SIGINT, вывод консоли впоследствии скрыт (т.е. консоль / терминал ведет себя как применение команды "stty -echo").

Я уже вставил код 'system ("stty echo"); в функции CleanupHandler перед выходом, и это «решило» проблему, но это не может быть правильным решением ... Возможно, я пропускаю серьезную ошибку, которая просто не появляется. Я также просто не понимаю, как мой код влияет на сам вывод / терминал консоли после завершения, потому что нет никакого системного вызова / вызова функции, который мог бы изменить поведение консоли (я использую только «printf» и цветовое форматирование для консоли выход).

Приведенный выше фрагмент кода должен воспроизвести проблему, конфигурация компилятора / компоновщика и выходные данные:

make all 
Building file: ../main.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.cpp"
Finished building: ../main.cpp

Building target: Testproject
Invoking: GCC C++ Linker
g++  -o"Testproject"  ./DebugInterface.o ./main.o   -lreadline -lpthread
Finished building target: Testproject

Я занимаюсь удаленной разработкой на сервере, проблема возникает таким же образом и по SSH, так что это не может быть консольной ошибкой. Кроме того, размещение обработчика ввода консоли в основном потоке и основных функций / цикла в дочернем потоке не имеет значения.

Заранее спасибо за любую помощь.

Ответы [ 3 ]

4 голосов
/ 21 июля 2009

Ваша программа не завершает свою работу при получении сигнала. Причиной является библиотека readline.

Проверьте, что говорит документация readline об обработке сигналов здесь

1 голос
/ 21 июля 2009

Запустите код под strace, и вы можете точно определить, где отключен выход терминала.

0 голосов
/ 23 июля 2009

Спасибо, добавление двух функций очистки в соответствии с библиотекой GNU Readline решило проблему.

Вы должны добавить следующие функции перед выражением "delete debugInterface;":

rl_cleanup_after_signal();
rl_free_line_state();

[...]

delete debugInterface;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...