@@ -619,21 +619,35 @@ listenerRun(void *data)
619619 socklen_t len ;
620620 fd_set listen_fds ; /* temp file descriptor list for select() */
621621
622- /* TODO: this thread won't die by restarting the server */
623622 /* TODO: HTTP is not handled */
624- while (1 ) {
623+ while (rfbIsActive ( screen ) ) {
625624 client_fd = -1 ;
626625 FD_ZERO (& listen_fds );
627626 if (screen -> listenSock != RFB_INVALID_SOCKET )
628627 FD_SET (screen -> listenSock , & listen_fds );
629628 if (screen -> listen6Sock != RFB_INVALID_SOCKET )
630629 FD_SET (screen -> listen6Sock , & listen_fds );
630+ #ifndef WIN32
631+ FD_SET (screen -> pipe_notify_listener_thread [0 ], & listen_fds );
632+ screen -> maxFd = rfbMax (screen -> maxFd , screen -> pipe_notify_listener_thread [0 ]);
633+ #endif
631634
632635 if (select (screen -> maxFd + 1 , & listen_fds , NULL , NULL , NULL ) == -1 ) {
633636 rfbLogPerror ("listenerRun: error in select" );
634637 return THREAD_ROUTINE_RETURN_VALUE ;
635638 }
636-
639+
640+ #ifndef WIN32
641+ if (FD_ISSET (screen -> pipe_notify_listener_thread [0 ], & listen_fds ))
642+ {
643+ /* Reset the pipe */
644+ char buf ;
645+ while (read (screen -> pipe_notify_listener_thread [0 ], & buf , sizeof (buf )) == sizeof (buf ));
646+ /* Go on with loop */
647+ continue ;
648+ }
649+ #endif
650+
637651 /* there is something on the listening sockets, handle new connections */
638652 len = sizeof (peer );
639653 if (FD_ISSET (screen -> listenSock , & listen_fds ))
@@ -921,6 +935,10 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
921935 screen -> maxFd = 0 ;
922936 screen -> listenSock = RFB_INVALID_SOCKET ;
923937 screen -> listen6Sock = RFB_INVALID_SOCKET ;
938+ #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
939+ screen -> pipe_notify_listener_thread [0 ] = -1 ;
940+ screen -> pipe_notify_listener_thread [1 ] = -1 ;
941+ #endif
924942
925943 screen -> fdQuota = 0.5 ;
926944
@@ -1180,6 +1198,21 @@ void rfbShutdownServer(rfbScreenInfoPtr screen,rfbBool disconnectClients) {
11801198
11811199 rfbHttpShutdownSockets (screen );
11821200 rfbShutdownSockets (screen );
1201+
1202+ #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
1203+ if (screen -> backgroundLoop ) {
1204+ /*
1205+ Notify the listener thread. This simply writes a NULL byte to the notify pipe in order to get past the select()
1206+ in listenerRun, the loop in there will then break because the rfbShutdownSockets() above has set screen->socketState.
1207+ */
1208+ write (screen -> pipe_notify_listener_thread [1 ], "\x00" , 1 );
1209+ /* And wait for it to finish. */
1210+ pthread_join (screen -> listener_thread , NULL );
1211+ /* Now we can close the pipe */
1212+ close (screen -> pipe_notify_listener_thread [0 ]);
1213+ close (screen -> pipe_notify_listener_thread [1 ]);
1214+ }
1215+ #endif
11831216}
11841217
11851218#if !defined LIBVNCSERVER_HAVE_GETTIMEOFDAY && defined WIN32
@@ -1287,15 +1320,19 @@ void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground
12871320{
12881321 if (runInBackground ) {
12891322#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
1290- pthread_t listener_thread ;
1291-
12921323 screen -> backgroundLoop = TRUE;
1293-
1294- pthread_create (& listener_thread , NULL , listenerRun , screen );
1324+ #ifndef WIN32
1325+ if (pipe (screen -> pipe_notify_listener_thread ) == -1 ) {
1326+ screen -> pipe_notify_listener_thread [0 ] = -1 ;
1327+ screen -> pipe_notify_listener_thread [1 ] = -1 ;
1328+ }
1329+ fcntl (screen -> pipe_notify_listener_thread [0 ], F_SETFL , O_NONBLOCK );
1330+ #endif
1331+ pthread_create (& screen -> listener_thread , NULL , listenerRun , screen );
12951332 return ;
12961333#elif defined(LIBVNCSERVER_HAVE_WIN32THREADS )
12971334 screen -> backgroundLoop = TRUE;
1298- _beginthread (listenerRun , 0 , screen );
1335+ screen -> listener_thread = _beginthread (listenerRun , 0 , screen );
12991336 return ;
13001337#else
13011338 rfbErr ("Can't run in background, because I don't have PThreads!\n" );
0 commit comments