diff --git a/include/rfb/rfb.h b/include/rfb/rfb.h index 79a446f1..86c6a5ff 100644 --- a/include/rfb/rfb.h +++ b/include/rfb/rfb.h @@ -707,6 +707,12 @@ typedef struct _rfbClientRec { int tightPngDstDataLen; #endif #endif + + /** for thread safety for updateBuf in rfbSendFBUpdate() */ +#if defined(LIBVNCSERVER_HAVE_LIBPTHREAD) || defined(LIBVNCSERVER_HAVE_WIN32THREADS) + MUTEX(updateBufMutex); +#endif + } rfbClientRec, *rfbClientPtr; /** diff --git a/src/libvncserver/main.c b/src/libvncserver/main.c index 1efa8387..d8c02684 100644 --- a/src/libvncserver/main.c +++ b/src/libvncserver/main.c @@ -1299,7 +1299,9 @@ rfbUpdateClient(rfbClientPtr cl) !sraRgnEmpty(cl->requestedRegion)) { result=TRUE; if(screen->deferUpdateTime == 0) { + LOCK(cl->updateBufMutex); rfbSendFramebufferUpdate(cl,cl->modifiedRegion); + UNLOCK(cl->updateBufMutex); } else if(cl->startDeferring.tv_usec == 0) { gettimeofday(&cl->startDeferring,NULL); if(cl->startDeferring.tv_usec == 0) @@ -1311,7 +1313,9 @@ rfbUpdateClient(rfbClientPtr cl) +(tv.tv_usec-cl->startDeferring.tv_usec)/1000) > screen->deferUpdateTime) { cl->startDeferring.tv_usec = 0; + LOCK(cl->updateBufMutex); rfbSendFramebufferUpdate(cl,cl->modifiedRegion); + UNLOCK(cl->updateBufMutex); } } } diff --git a/src/libvncserver/rfbserver.c b/src/libvncserver/rfbserver.c index a80fd1ae..6a404cf3 100644 --- a/src/libvncserver/rfbserver.c +++ b/src/libvncserver/rfbserver.c @@ -378,6 +378,8 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen, INIT_MUTEX(cl->sendMutex); INIT_COND(cl->deleteCond); + INIT_MUTEX(cl->updateBufMutex); + cl->state = RFB_PROTOCOL_VERSION; cl->reverseConnection = FALSE; @@ -650,6 +652,11 @@ rfbClientConnectionGone(rfbClientPtr cl) UNLOCK(cl->sendMutex); TINI_MUTEX(cl->sendMutex); + /* make sure updateBufMutex is unlocked before destroying */ + LOCK(cl->updateBufMutex); + UNLOCK(cl->updateBufMutex); + TINI_MUTEX(cl->updateBufMutex); + #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD if (cl->screen->backgroundLoop) { close(cl->pipe_notify_client_thread[0]);