Всем добрый день. пишу простенькую прожку висящую в трее и сообщающую пользователям некую полузную инфу. Столкнулся с проблемой совмещения всплывающих уведомлений через libnotify с gtk_main() циклом находящихся в разных потоках, т.е. первый поток обслуживает gtk_main() для иконки в трее, а во втором потоке крутится цикл который при определенных обстоятельствах и выводит всплывающие уведомления.
Теперь о проблеме более подробно: если вызывать всплывающее уведомление сигналом из иконки (первый поток), то все отрабатывает на ура, но как только всплывающее уведомление должно вызваться во втором потоке прога вылетает с ошибкой сегментирования. Более того, если из всего кода выкинуть саму ф-цию вывода всплывающего сообщения notify_notification_show() и заменить на простой printf (что б видеть что ф-ция отрабатывает), то все отрабатывает без сбоев, но как только вызывается notify_notification_show() вылетает ошибка памяти, причем может 20 раз подряд вылетать ошибка, потом вдруг прога запустилась, цикл 2-3 раза вывел нормально всплывающее уведомление и опять вылетел с ошибкой памяти.
Гугл оказался неразговорчив на эту тему, поиск по форуму не дал ничего похожего. Может кто писал что-то подобное и знает как правильно нужно сделать? Вобщем нужна помощь в данном вопросе. Хочется разобраться именно с libnotify и не прибегать к костылям типа system(«notify-send text»)
сам код примера:
#include <pthread.h>
#include <semaphore.h>
#include <gtk/gtk.h>
#include <libnotify/notify.h>
#include <unistd.h>
#include <cstdlib>
using namespace std;
class sysTrayIcon;
class notify;
pthread_t thread1, thread2;
int threadID1, threadID2;
sem_t sem;
sysTrayIcon *picon;
notify *pnotify;
void *thread_func_notify(void *);
void *thread_func_tray(void *);
static void tray_icon_activated(GtkStatusIcon *, gpointer);
static void tray_icon_quit_prog(GtkStatusIcon *, gpointer);
static void tray_icon_popup_menu(GtkStatusIcon *, guint, guint32, gpointer);
class sysTrayIcon
{
const gchar *icon_file;
GtkStatusIcon *trayIcon;
GtkWidget *menu, *menuitem;
public:
sysTrayIcon();
void show();
};
class notify
{
NotifyNotification *idNotify;
public:
notify();
void show(unsigned long);
};
sysTrayIcon::sysTrayIcon()
{
icon_file = "path_to_file.png";
}
void sysTrayIcon::show()
{
gtk_init(NULL,NULL);
trayIcon = gtk_status_icon_new();
gtk_status_icon_set_from_file(trayIcon,icon_file);
gtk_status_icon_set_visible(trayIcon,true);
g_signal_connect(trayIcon,"activate",G_CALLBACK(tray_icon_activated),NULL);
menu = gtk_menu_new();
menuitem = gtk_menu_item_new_with_label("Выйти");
g_signal_connect(G_OBJECT(menuitem),"activate",G_CALLBACK(tray_icon_quit_prog),NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(menu),menuitem);
gtk_widget_show_all(menu);
g_signal_connect(trayIcon,"popup-menu",G_CALLBACK(tray_icon_popup_menu),menu);
sem_post(&sem);
gtk_main();
}
static void tray_icon_activated(GtkStatusIcon *icon, gpointer data)
{
pnotify->show(5);
}
static void tray_icon_quit_prog(GtkStatusIcon *icon, gpointer data)
{
pthread_cancel(thread2);
pthread_cancel(thread1);
gtk_main_quit();
}
static void tray_icon_popup_menu(GtkStatusIcon *trayIcon, guint button, guint32 activate_time, gpointer menu)
{
gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,trayIcon,button,activate_time);
}
notify::notify()
{
notify_init("test init");
idNotify = notify_notification_new("test","test",NULL,NULL);
}
void notify::show(unsigned long sec)
{
notify_notification_update(idNotify,"test notify","body of notification",NULL);
notify_notification_set_timeout(idNotify,sec*1000);
printf("ok\n");
notify_notification_show(idNotify,NULL);
}
int main(int argc, char *argv[])
{
sysTrayIcon hicon;
notify hnotify;
picon = &hicon;
pnotify = &hnotify;
sem_init(&sem,0,0);
if (pthread_create(&thread1,NULL,thread_func_tray,&threadID1))
{
printf("Dont`t creating Tray function\n");
exit(1);
}
sem_wait(&sem);
if (pthread_create(&thread2,NULL,thread_func_notify,&threadID2))
{
printf("Dont`t creating Notifycation function\n");
exit(1);
}
if (pthread_join(thread1,NULL))
{
printf("Joining Tray function\n");
exit(1);
}
if (pthread_join(thread2,NULL))
{
printf("Joining Notifycation function\n");
exit(1);
}
sem_destroy(&sem);
}
void *thread_func_tray(void *data)
{
picon->show();
}
void *thread_func_notify(void *data)
{
sem_post(&sem);
while (1)
{
pnotify->show(3);
sleep(5);
}
}
компилю так:
g++ test.cpp -o test -lnotify -lpthread `pkg-config --cflags --libs gtk+-2.0`
g++ test.cpp -o test -D_REENTRANT -lnotify -lpthread `pkg-config --cflags --libs gtk+-2.0`