summaryrefslogtreecommitdiff
path: root/src/wins.c
diff options
context:
space:
mode:
authorLukas Fleischer <calcurse@cryptocrack.de>2012-11-23 10:41:20 +0100
committerLukas Fleischer <calcurse@cryptocrack.de>2012-11-23 11:12:08 +0100
commit0ea23c24bf06e153bb075804e195e1733fd67d3f (patch)
tree740ec1c36e1b78143350e6cb079faa187f99049d /src/wins.c
parenta80f8dcf2c6eb3b54658218bc081ee9694204dd5 (diff)
downloadcalcurse-0ea23c24bf06e153bb075804e195e1733fd67d3f.zip
Release screen mutex if thread dies
We did not setup a thread cleanup procedure which resulted in calcurse freezing if a thread tried to draw on the screen after another thread was canceled while locking the screen. Note that this kind of cleanup handlers should be added to other mutexes as well. This patch just removes the most common case of triggering a deadlock. Also note that we cannot move pthread_cleanup_push() and pthread_cleanup_pop() into the locking/unlocking functions since both pthread_cleanup_push() and pthread_cleanup_pop() may be implemented as macros that must be used in pairs within the same lexical scope. Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
Diffstat (limited to 'src/wins.c')
-rw-r--r--src/wins.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/src/wins.c b/src/wins.c
index 64dd962..249610c 100644
--- a/src/wins.c
+++ b/src/wins.c
@@ -40,6 +40,14 @@
#include "calcurse.h"
+#define SCREEN_ACQUIRE \
+ pthread_cleanup_push(screen_cleanup, (void *)NULL); \
+ screen_acquire();
+
+#define SCREEN_RELEASE \
+ screen_release(); \
+ pthread_cleanup_pop(0);
+
/* Variables to handle calcurse windows. */
struct window win[NBWINS];
@@ -76,6 +84,11 @@ static void screen_release(void)
pthread_mutex_unlock(&screen_mutex);
}
+static void screen_cleanup(void *arg)
+{
+ screen_release();
+}
+
/*
* FIXME: The following functions currently lock the whole screen. Use both
* window-level and screen-level mutexes (or use use_screen() and use_window(),
@@ -92,6 +105,11 @@ void wins_nbar_unlock(void)
screen_release();
}
+void wins_nbar_cleanup(void *arg)
+{
+ wins_nbar_unlock();
+}
+
unsigned wins_calendar_lock(void)
{
return screen_acquire();
@@ -102,14 +120,18 @@ void wins_calendar_unlock(void)
screen_release();
}
+void wins_calendar_cleanup(void *arg)
+{
+ wins_calendar_unlock();
+}
+
int wins_refresh(void)
{
int rc;
- if (!screen_acquire())
- return ERR;
+ SCREEN_ACQUIRE;
rc = refresh();
- screen_release();
+ SCREEN_RELEASE;
return rc;
}
@@ -118,10 +140,11 @@ int wins_wrefresh(WINDOW * win)
{
int rc;
- if (!win || !screen_acquire())
+ if (!win)
return ERR;
+ SCREEN_ACQUIRE;
rc = wrefresh(win);
- screen_release();
+ SCREEN_RELEASE;
return rc;
}
@@ -130,10 +153,9 @@ int wins_doupdate(void)
{
int rc;
- if (!screen_acquire())
- return ERR;
+ SCREEN_ACQUIRE;
rc = doupdate();
- screen_release();
+ SCREEN_RELEASE;
return rc;
}
@@ -502,12 +524,12 @@ static void border_nocolor(WINDOW * window)
void wins_update_border(int flags)
{
if (flags & FLAG_CAL) {
- wins_calendar_lock();
+ WINS_CALENDAR_LOCK;
if (slctd_win == CAL)
border_color(win[CAL].p);
else
border_nocolor(win[CAL].p);
- wins_calendar_unlock();
+ WINS_CALENDAR_UNLOCK;
}
if (flags & FLAG_APP) {
if (slctd_win == APP)