Подробности

[В начало]

Проблема в реализации № D0024

Краткое описание

Вызов функции "g_thread_pool_free" с определенными входными параметрами приводит к сообщению об ошибке

Подробное описание

Вызов функции g_thread_pool_free со следующими входными параметрами: "immediate" = TRUE "wait" = FALSE приводит к сообщению об ошибке: "g_thread_pool_wakeup_and_stop_all: assertion `g_async_queue_length_unlocked (pool->queue) == -pool->num_threads' failed".

Раздел стандарта

Linux Standard Base Desktop Specification 3.1, Chapter 12. Libraries, 12.2 Interfaces for libglib-2.0; http://www.gtk.org/api/2.6/glib/glib-Thread-Pools.html#g-thread-pool-free

Способ воспроизведения

  1. В пул потоков добавляется 10 заданий.
  2. После завершения первого задания вызывается "g_thread_pool_free (pool, TRUE, FALSE)", что приводит к следующей ошибке: "g_thread_pool_wakeup_and_stop_all: assertion `g_async_queue_length_unlocked (pool->queue) == -pool->num_threads' failed".

Пример

#include <glib.h>
#include <sys/wait.h>

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <semaphore.h>




#define VAR(function, name, tp_index)  _##function##_TP_##tp_index##_##name
#define FUNC(function, name, tp_index) __##function##_TP_##tp_index##_##name
#define TP_FUNC(function, tp_index) _##function##_TP_##tp_index##_



#define TIMED_WAIT(condition, seconds)\
  	int __tw_expired=0; struct timeval __tv;gettimeofday(&__tv, NULL);\
    long __st_sec=__tv.tv_sec;\
	while(condition) {g_usleep(100);gettimeofday(&__tv, NULL);\
    if((__tv.tv_sec - __st_sec)>seconds){ __tw_expired=1;break;}}

#define TIMED_WAIT_EXPIRED __tw_expired


#define TIMED_WAIT_2(condition, seconds)\
  	__tw_expired=0;gettimeofday(&__tv, NULL);__st_sec=__tv.tv_sec;\
	while(condition) {g_usleep(100);gettimeofday(&__tv, NULL);\
    if((__tv.tv_sec - __st_sec)>seconds) { __tw_expired=1;break;}}



#define _DECLARE_G_SEMAPHORE(s_name) sem_t s_name;

#define _G_SUNLOCK(s_name)  sem_post(&s_name);

#define _G_STIMED_WAIT(seconds, s_name, exp_var, tumeout_st)\
	int exp_var=0;struct timespec tumeout_st;\
    clock_gettime(CLOCK_REALTIME, &tumeout_st);tumeout_st.tv_sec += seconds;\
	if(sem_timedwait(&s_name, &tumeout_st) != 0)\
    {if(errno == ETIMEDOUT) exp_var=1;}

#define _G_STIMED_WAIT_2(seconds, s_name, exp_var, tumeout_st)\
	exp_var=0;clock_gettime(CLOCK_REALTIME, &tumeout_st);\
    tumeout_st.tv_sec += seconds;\
	if(sem_timedwait(&s_name, &tumeout_st) != 0){if(errno == ETIMEDOUT) \
    exp_var=1;}

#define _G_STIMED_WAIT_EXPIRED(exp_var) exp_var


#define DECLARE_G_SEMAPHORE 		_DECLARE_G_SEMAPHORE(_g_sem_)
#define G_SUNLOCK 					_G_SUNLOCK(_g_sem_)
#define G_STIMED_WAIT(seconds) 		\
    _G_STIMED_WAIT(seconds, _g_sem_, __stw_expired, __stimeout)
#define G_STIMED_WAIT_2(seconds)	\
    _G_STIMED_WAIT_2(seconds, _g_sem_, __stw_expired, __stimeout)
#define G_STIMED_WAIT_EXPIRED		\
    _G_STIMED_WAIT_EXPIRED(__stw_expired)


#define DECLARE_G_SEMAPHORE_EX 		_DECLARE_G_SEMAPHORE(_g_sem_2)
#define G_SUNLOCK_EX 				_G_SUNLOCK(_g_sem_2)
#define G_STIMED_WAIT_EX(seconds) 	\
    _G_STIMED_WAIT(seconds, _g_sem_2, __stw_expired_2, __stimeout_2)
#define G_STIMED_WAIT_2_EX(seconds)	\
    _G_STIMED_WAIT_2(seconds, _g_sem_2, __stw_expired_2, __stimeout_2)
#define G_STIMED_WAIT_EXPIRED_EX	\
    _G_STIMED_WAIT_EXPIRED(__stw_expired_2)

#define DECLARE_G_SEMAPHORE_EX_2 		_DECLARE_G_SEMAPHORE(_g_sem_3)
#define G_SUNLOCK_EX_2 					_G_SUNLOCK(_g_sem_3)
#define G_STIMED_WAIT_EX_2(seconds) 	\
    _G_STIMED_WAIT(seconds, _g_sem_3, __stw_expired_3, __stimeout_3)
#define G_STIMED_WAIT_2_EX_2(seconds)	\
    _G_STIMED_WAIT_2(seconds, _g_sem_3, __stw_expired_3, __stimeout_3)
#define G_STIMED_WAIT_EXPIRED_EX_2		\
    _G_STIMED_WAIT_EXPIRED(__stw_expired_3)


DECLARE_G_SEMAPHORE
DECLARE_G_SEMAPHORE_EX
DECLARE_G_SEMAPHORE_EX_2


#define IMMEDIATE   TRUE
#define WAIT        FALSE

int glob_count = 0;
GStaticMutex func_mutex = G_STATIC_MUTEX_INIT;

void initGlobalSemaphores()
{
    sem_init(&_g_sem_, 0, 0);
    sem_init(&_g_sem_2, 0, 0);
    sem_init(&_g_sem_3, 0, 0);
}

void func_free (gpointer data, gpointer user_data)
{
    g_static_mutex_lock (&func_mutex);
    int count  = glob_count;
    g_static_mutex_unlock (&func_mutex);
    if (count == 1)
    {
        G_SUNLOCK;
        G_STIMED_WAIT_EX (3);
    }

    g_static_mutex_lock (&func_mutex);
    count = ++glob_count;
    g_static_mutex_unlock (&func_mutex);

    if (count == 1)
    {
        G_SUNLOCK;
    }
}

int main ()
{
    g_thread_init (NULL);
    GThreadPool *pool = NULL;
    char *_data = "data";
    int thread_count = 10;
    initGlobalSemaphores ();

    g_static_mutex_lock (&func_mutex);
    glob_count = 0;
    g_static_mutex_unlock (&func_mutex);

    pool = g_thread_pool_new (func_free, "unprocessed pool", 1, FALSE, NULL);

	int i;
    for ( i = 0; i < thread_count; i++)
    {
        g_thread_pool_push (pool, _data, NULL);
    }
    G_STIMED_WAIT (3);
    G_STIMED_WAIT_2 (3);

    g_thread_pool_free (pool, IMMEDIATE, WAIT);
    return 0;
}

Компонент

gtk-glib 2.6.2 - 2.12.4(excl.)

Статус

Исправлено в gtk-glib - 2.12.4

[В начало]