I just figured out how to do that, polling the std::cin file descriptor.
poll function returns 0 if timeout occurs and no event happened, 1 if something happened, and -1 if error happened.
#include <iostream>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
bool stop = false;
void intHandler(int dummy)
{
    stop = true;
}
std::string readStdIn()
{
    struct pollfd pfd = { STDIN_FILENO, POLLIN, 0 };
    std::string line;
    int ret = 0;
    while(ret == 0)
    {
        ret = poll(&pfd, 1, 1000);  // timeout of 1000ms
        if(ret == 1) // there is something to read
        {
            std::getline(std::cin, line);
        }
        else if(ret == -1)
        {
            std::cout << "Error: " << strerror(errno) << std::endl;
        }
    }
    return line;
}
int main(int argc, char * argv[])
{
    signal(SIGINT, intHandler);
    signal(SIGKILL, intHandler);
    while(!stop)
    {
        std::string line = readStdIn();
        std::cout << "Read: " << line << std::endl;
    }
    std::cout << "gracefully shutdown" << std::endl;
}