summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--VisualNaCro/nacro.c6
-rw-r--r--VisualNaCro/nacro.h4
-rw-r--r--examples/example.c9
-rw-r--r--examples/fontsel.c4
-rwxr-xr-xlibvncserver/httpd.c7
-rw-r--r--libvncserver/main.c24
-rw-r--r--libvncserver/rfbserver.c5
-rwxr-xr-xlibvncserver/sockets.c29
-rw-r--r--rfb/rfb.h12
-rwxr-xr-xtest/cursortest.c1
-rw-r--r--vncterm/LinuxVNC.c2
-rw-r--r--vncterm/VNConsole.c5
-rw-r--r--x11vnc/x11vnc.c2
14 files changed, 96 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 827d780..f72130c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2005-05-07 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
+ * libvncserver/rfbserver.c: fix memory leak pointed out by Tim Jansen
+ * libvncserver/{httpd,main,rfbserver,sockets}.c, rfb/rfb.h:
+ replace "rfbBool socketInitDone" by "enum rfbSocketState
+ socketState"
+
2005-05-03 Karl Runge <runge@karlrunge.com>
* libvncserver/main.c: fix leak in rfbDoCopyRect/rfbScheduleCopyRect
* configure.ac: guard against empty HAVE_X
diff --git a/VisualNaCro/nacro.c b/VisualNaCro/nacro.c
index eda2887..9d4e9ed 100644
--- a/VisualNaCro/nacro.c
+++ b/VisualNaCro/nacro.c
@@ -327,7 +327,11 @@ result_t private_process(resource_t resource,timeout_t timeout_in_seconds,result
rfbBool loop;
do {
loop=rfbProcessEvents(res->server,res->server->deferUpdateTime);
- } while(loop && (res->result&return_mask)==0);
+ } while(loop && (res->result&return_mask)==0
+ && rfbIsActive(res->server));
+
+ if(!rfbIsActive(res->server))
+ return RESULT_SHUTDOWN;
if((res->result&return_mask)!=0)
return res->result;
diff --git a/VisualNaCro/nacro.h b/VisualNaCro/nacro.h
index ec75630..c4a8581 100644
--- a/VisualNaCro/nacro.h
+++ b/VisualNaCro/nacro.h
@@ -29,11 +29,12 @@ typedef double timeout_t;
/* the return values of process() and friends */
typedef int result_t;
/*
- * %constant int RESULT_TIMEOUT=1;
+%constant int RESULT_TIMEOUT=1;
%constant int RESULT_KEY=2;
%constant int RESULT_MOUSE=4;
%constant int RESULT_SCREEN=8;
%constant int RESULT_FOUNDIMAGE=16;
+%constant int RESULT_SHUTDOWN=32;
*/
%}
@@ -52,6 +53,7 @@ typedef int result_t;
#define RESULT_MOUSE 4
#define RESULT_SCREEN 8
#define RESULT_FOUNDIMAGE 16
+#define RESULT_SHUTDOWN 32
/* init/shutdown */
diff --git a/examples/example.c b/examples/example.c
index da1385e..f4a1f08 100644
--- a/examples/example.c
+++ b/examples/example.c
@@ -168,6 +168,12 @@ void dokey(rfbBool down,rfbKeySym key,rfbClientPtr cl)
if(down) {
if(key==XK_Escape)
rfbCloseClient(cl);
+ else if(key==XK_F12)
+ /* close down server, disconnecting clients */
+ rfbShutdownServer(cl->screen,TRUE);
+ else if(key==XK_F11)
+ /* close down server, but wait for all clients to disconnect */
+ rfbShutdownServer(cl->screen,FALSE);
else if(key==XK_Page_Up) {
initBuffer((unsigned char*)cl->screen->frameBuffer);
rfbMarkRectAsModified(cl->screen,0,0,maxx,maxy);
@@ -294,7 +300,7 @@ int main(int argc,char** argv)
#ifdef USE_OWN_LOOP
{
int i;
- for(i=0;;i++) {
+ for(i=0;rfbIsActive(rfbScreen);i++) {
fprintf(stderr,"%d\r",i);
rfbProcessEvents(rfbScreen,100000);
}
@@ -315,7 +321,6 @@ int main(int argc,char** argv)
while(1) sleep(5); /* render(); */
#endif /* BACKGROUND_LOOP */
- rfbFreeCursor(rfbScreen->cursor);
free(rfbScreen->frameBuffer);
rfbScreenCleanup(rfbScreen);
diff --git a/examples/fontsel.c b/examples/fontsel.c
index 4aa702c..a2a2f82 100644
--- a/examples/fontsel.c
+++ b/examples/fontsel.c
@@ -58,13 +58,15 @@ int main(int argc,char** argv)
exit(1);
}
- for(j=0;j<0;j++)
+ for(j=0;j<0 && rfbIsActive(s);j++)
rfbProcessEvents(s,900000);
i = rfbSelectBox(s,font,fontlist,10,20,200,300,0xffdfdf,0x602040,2,showFont);
rfbLog("Selection: %d: %s\n",i,(i>=0)?fontlist[i]:"cancelled");
rfbFreeFont(font);
+ free(s->frameBuffer);
+ rfbScreenCleanup(s);
return(0);
}
diff --git a/libvncserver/httpd.c b/libvncserver/httpd.c
index b973bb6..f341d1a 100755
--- a/libvncserver/httpd.c
+++ b/libvncserver/httpd.c
@@ -111,6 +111,13 @@ rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen)
/*AddEnabledDevice(httpListenSock);*/
}
+void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) {
+ if(rfbScreen->httpSock>-1) {
+ close(rfbScreen->httpSock);
+ FD_CLR(rfbScreen->httpSock,&rfbScreen->allFds);
+ rfbScreen->httpSock=-1;
+ }
+}
/*
* httpCheckFds is called from ProcessInputEvents to check for input on the
diff --git a/libvncserver/main.c b/libvncserver/main.c
index 529bf2a..d2dc69f 100644
--- a/libvncserver/main.c
+++ b/libvncserver/main.c
@@ -543,7 +543,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
screen->clientHead=0;
screen->pointerClient=0;
screen->port=5900;
- screen->socketInitDone=FALSE;
+ screen->socketState=RFB_SOCKET_INIT;
screen->inetdInitDone = FALSE;
screen->inetdSock=-1;
@@ -729,7 +729,7 @@ void rfbScreenCleanup(rfbScreenInfoPtr screen)
FREE_IF(colourMap.data.bytes);
FREE_IF(underCursorBuffer);
TINI_MUTEX(screen->cursorMutex);
- if(screen->cursor)
+ if(screen->cursor && screen->cursor->cleanup)
rfbFreeCursor(screen->cursor);
free(screen);
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
@@ -751,6 +751,20 @@ void rfbInitServer(rfbScreenInfoPtr screen)
#endif
}
+void rfbShutdownServer(rfbScreenInfoPtr screen,rfbBool disconnectClients) {
+ if(disconnectClients) {
+ rfbClientPtr cl;
+ rfbClientIteratorPtr iter = rfbGetClientIterator(screen);
+ while( (cl = rfbClientIteratorNext(iter)) )
+ if (cl->sock > -1)
+ /* we don't care about maxfd here, because the server goes away */
+ rfbCloseClient(cl);
+ }
+
+ rfbShutdownSockets(screen);
+ rfbHttpShutdownSockets(screen);
+}
+
#ifndef LIBVNCSERVER_HAVE_GETTIMEOFDAY
#include <fcntl.h>
#include <conio.h>
@@ -820,6 +834,10 @@ rfbProcessEvents(rfbScreenInfoPtr screen,long usec)
return result;
}
+rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo) {
+ return screenInfo->socketState!=RFB_SOCKET_SHUTDOWN || screenInfo->clientHead!=NULL;
+}
+
void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground)
{
if(runInBackground) {
@@ -839,6 +857,6 @@ void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground
if(usec<0)
usec=screen->deferUpdateTime*1000;
- while(1)
+ while(rfbIsActive(screen))
rfbProcessEvents(screen,usec);
}
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index e218fea..74f4fbd 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -354,10 +354,7 @@ rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP)
if (rfbWriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) {
rfbLogPerror("rfbNewClient: write");
rfbCloseClient(cl);
- /* TODO: memory leak here (cl is never freed)
- * can rfbClientConnectionGone called at this time?
- * tim@tjansen.de
- */
+ rfbClientConnectionGone(cl);
return NULL;
}
}
diff --git a/libvncserver/sockets.c b/libvncserver/sockets.c
index 0aba2dc..9025df8 100755
--- a/libvncserver/sockets.c
+++ b/libvncserver/sockets.c
@@ -104,10 +104,10 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen)
{
in_addr_t iface = rfbScreen->listenInterface;
- if (rfbScreen->socketInitDone)
+ if (rfbScreen->socketState!=RFB_SOCKET_INIT)
return;
- rfbScreen->socketInitDone = TRUE;
+ rfbScreen->socketState = RFB_SOCKET_READY;
if (rfbScreen->inetdSock != -1) {
const int one = 1;
@@ -176,6 +176,31 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen)
}
}
+void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen)
+{
+ if (rfbScreen->socketState!=RFB_SOCKET_READY)
+ return;
+
+ rfbScreen->socketState = RFB_SOCKET_SHUTDOWN;
+
+ if(rfbScreen->inetdSock>-1) {
+ close(rfbScreen->inetdSock);
+ FD_CLR(rfbScreen->inetdSock,&rfbScreen->allFds);
+ rfbScreen->inetdSock=-1;
+ }
+
+ if(rfbScreen->listenSock>-1) {
+ close(rfbScreen->listenSock);
+ FD_CLR(rfbScreen->listenSock,&rfbScreen->allFds);
+ rfbScreen->listenSock=-1;
+ }
+
+ if(rfbScreen->udpSock>-1) {
+ close(rfbScreen->udpSock);
+ FD_CLR(rfbScreen->udpSock,&rfbScreen->allFds);
+ rfbScreen->udpSock=-1;
+ }
+}
/*
* rfbCheckFds is called from ProcessInputEvents to check for input on the RFB
diff --git a/rfb/rfb.h b/rfb/rfb.h
index 660baab..0c9ad21 100644
--- a/rfb/rfb.h
+++ b/rfb/rfb.h
@@ -116,6 +116,12 @@ enum rfbNewClientAction {
RFB_CLIENT_REFUSE
};
+enum rfbSocketState {
+ RFB_SOCKET_INIT,
+ RFB_SOCKET_READY,
+ RFB_SOCKET_SHUTDOWN
+};
+
typedef void (*rfbKbdAddEventProcPtr) (rfbBool down, rfbKeySym keySym, struct _rfbClientRec* cl);
typedef void (*rfbKbdReleaseAllKeysProcPtr) (struct _rfbClientRec* cl);
typedef void (*rfbPtrAddEventProcPtr) (int buttonMask, int x, int y, struct _rfbClientRec* cl);
@@ -178,7 +184,7 @@ typedef struct _rfbScreenInfo
fd_set allFds;
#endif
- rfbBool socketInitDone;
+ enum rfbSocketState socketState;
SOCKET inetdSock;
rfbBool inetdInitDone;
@@ -500,6 +506,7 @@ extern char rfbEndianTest;
extern int rfbMaxClientWait;
extern void rfbInitSockets(rfbScreenInfoPtr rfbScreen);
+extern void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen);
extern void rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen);
extern void rfbCloseClient(rfbClientPtr cl);
extern int rfbReadExact(rfbClientPtr cl, char *buf, int len);
@@ -563,6 +570,7 @@ extern void rfbSetClientColourMaps(rfbScreenInfoPtr rfbScreen, int firstColour,
/* httpd.c */
extern void rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen);
+extern void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen);
extern void rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen);
@@ -741,6 +749,7 @@ extern rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
int width,int height,int bitsPerSample,int samplesPerPixel,
int bytesPerPixel);
extern void rfbInitServer(rfbScreenInfoPtr rfbScreen);
+extern void rfbShutdownServer(rfbScreenInfoPtr rfbScreen,rfbBool disconnectClients);
extern void rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen,char *framebuffer,
int width,int height, int bitsPerSample,int samplesPerPixel,
int bytesPerPixel);
@@ -761,6 +770,7 @@ extern void rfbRefuseOnHoldClient(rfbClientPtr cl);
extern void rfbRunEventLoop(rfbScreenInfoPtr screenInfo, long usec, rfbBool runInBackground);
extern rfbBool rfbProcessEvents(rfbScreenInfoPtr screenInfo,long usec);
+extern rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo);
#endif
diff --git a/test/cursortest.c b/test/cursortest.c
index 8e98aed..4c75f23 100755
--- a/test/cursortest.c
+++ b/test/cursortest.c
@@ -343,7 +343,6 @@ int main(int argc,char** argv)
/* 40000 are the microseconds to wait on select(), i.e. 0.04 seconds */
rfbRunEventLoop(rfbScreen,40000,FALSE);
- rfbFreeCursor(rfbScreen->cursor);
free(rfbScreen->frameBuffer);
rfbScreenCleanup(rfbScreen);
diff --git a/vncterm/LinuxVNC.c b/vncterm/LinuxVNC.c
index 0905e74..bfff739 100644
--- a/vncterm/LinuxVNC.c
+++ b/vncterm/LinuxVNC.c
@@ -137,7 +137,7 @@ int main(int argc,char **argv)
sprintf(tty_device,"/dev/vcsa%d",tty);
#endif
- while(1) {
+ while(rfbIsActive(console->screen)) {
if(!console->currentlyMarking) {
tty_file=fopen(tty_device,"rb");
if(!tty_file) {
diff --git a/vncterm/VNConsole.c b/vncterm/VNConsole.c
index 651546a..ec3002f 100644
--- a/vncterm/VNConsole.c
+++ b/vncterm/VNConsole.c
@@ -328,7 +328,7 @@ char vcGetCh(vncConsolePtr c)
char vcGetChar(vncConsolePtr c)
{
- while(c->inputCount==0)
+ while(rfbIsActive(c->screen) && c->inputCount==0)
vcProcessEvents(c);
return(vcGetCh(c));
}
@@ -352,7 +352,8 @@ char *vcGetString(vncConsolePtr c,char *buffer,int bufferSize)
count=c->inputSize;
c->inputSize=bufferSize;
c->inputBuffer=buffer;
- while(c->inputCount<bufferSize-1 && buffer[c->inputCount-1]!='\n')
+ while(rfbIsActive(c->screen)
+ && c->inputCount<bufferSize-1 && buffer[c->inputCount-1]!='\n')
vcProcessEvents(c);
buffer[c->inputCount]=0;
c->inputBuffer=bufferBackup;
diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c
index 092c236..80eef99 100644
--- a/x11vnc/x11vnc.c
+++ b/x11vnc/x11vnc.c
@@ -9558,7 +9558,7 @@ void reset_rfbport(int old, int new) {
screen->autoPort = FALSE;
}
screen->port = rp;
- screen->socketInitDone = FALSE;
+ screen->socketState = RFB_SOCKET_INIT;
if (screen->listenSock > -1) {
close(screen->listenSock);