2013-11-08 3 views
5

Я знаю, что я могу установить имя потока (тот, который отображается в gdb и htop) в Linux using prctl(). Но с другими ОС это, скорее всего, не сработает. Кроме того, я мог бы попробовать using pthread_setname_np(), который немного больше доступен в системах POSIX, но по-прежнему не имеет полной совместимости.Есть ли способ переносить имя потока с помощью Qt?

Таким образом, я хотел бы иметь несколько более портативных способов, возможно, что-то QThread, которые я не нашел. Есть ли такой способ?

+0

Вы можете работать с флагами компиляции, в зависимости от ОС, для которой вы компилируете. – Theolodis

+0

boost не имеет никакого способа, поэтому я сомневаюсь, что QT будет –

ответ

6

Нет ничего в API QThread, чтобы вручную управлять системным именем потока, однако, поскольку версия 4.8.3, Qt автоматически задает имя вашего потока имени объекта потока (QObject::objectName()).

Это относится к реализациям QThread, как описано ниже.

У вас есть что-то подобное в qthread_unix.cpp:

#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX)) 
static void setCurrentThreadName(pthread_t threadId, const char *name) 
{ 
# if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE) 
    Q_UNUSED(threadId); 
    prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); 
# elif defined(Q_OS_MAC) 
    Q_UNUSED(threadId); 
    pthread_setname_np(name); 
# elif defined(Q_OS_QNX) 
    pthread_setname_np(threadId, name); 
# endif 
} 
#endif 

/* 
* [...] 
*/ 

QString objectName = thr->objectName(); 

if (Q_LIKELY(objectName.isEmpty())) 
    setCurrentThreadName(thr->d_func()->thread_id, thr->metaObject()->className()); 
else 
    setCurrentThreadName(thr->d_func()->thread_id, objectName.toLocal8Bit()); 

и эквивалент в qthread_win.cpp:

typedef struct tagTHREADNAME_INFO 
{ 
    DWORD dwType;  // must be 0x1000 
    LPCSTR szName;  // pointer to name (in user addr space) 
    HANDLE dwThreadID; // thread ID (-1=caller thread) 
    DWORD dwFlags;  // reserved for future use, must be zero 
} THREADNAME_INFO; 

void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) 
{ 
    THREADNAME_INFO info; 
    info.dwType = 0x1000; 
    info.szName = threadName; 
    info.dwThreadID = threadId; 
    info.dwFlags = 0; 

    __try 
    { 
     RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR*)&info); 
    } 
    __except (EXCEPTION_CONTINUE_EXECUTION) 
    { 
    } 
} 

/* 
* [...] 
*/ 

QByteArray objectName = thr->objectName().toLocal8Bit(); 
qt_set_thread_name((HANDLE)-1, objectName.isEmpty() ? thr->metaObject()->className() : objectName.constData()); 

Обратите внимание, что на Windows, приведенный выше код не будет выполняться, если QT_NO_DEBUG установлено, таким образом не будет работать в Релиз режим.

+0

Это похоже только на новые достаточно Qt-версии. Я не вижу поведения, указанного в @Marek в 4.8.1. Вместо этого все мои потоки имеют имя, совпадающее с именем двоичного. Кроме того, 'grep' для' setCurrentThreadName' не находит ничего в дистрибутивном исходном дереве. В любом случае, похоже, это первая реальная поддержка этого в Qt, поэтому я приму свой ответ. – Ruslan

+0

@ Ruslan Да, как вы можете видеть [здесь] (https://qt.gitorious.org/qt/qt/commit/aa21fcac3672cc6f0dca064b34bbe02ca4f4def7), эта функция была реализована для цели отладки. Я действительно удивлен тем, что на нем ссылается в документации Qt, поскольку это не намного больше, чем обходное решение для отладки. – zakinster

4

В Qt documentation вы можете найти:

Чтобы выбрать имя, которое ваш поток будет дан (как это определено команда п.с. -L на Linux, например), вы можете вызов setObjectName() перед началом темы. Если вы не вызываете setObjectName(), имя , присвоенное вашему потоку, будет имя класса типа среды выполнения вашего объекта потока (например, «RenderThread» в случае примера Mandelbrot, as это имя подкласса QThread). Отметьте , что в настоящее время он недоступен при выпуске релизов в Windows.