Tcl Source Code

Check-in [57e106c650]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix the Cygwin notifier, doing the initialization of the thread-local variables exactly the same as the Unix notifier.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | bug-5d170b5ca5
Files: files | file ages | folders
SHA1: 57e106c650de054ae957b5cddaa4ad828c416bb7
User & Date: jan.nijtmans 2015-09-02 11:54:58
Context
2015-09-03
09:39
In StartNotifierThread() don't lock mutex if thread is already started. Fix panic message if thread... check-in: 795a9a8bc0 user: jan.nijtmans tags: bug-5d170b5ca5
2015-09-02
11:54
Fix the Cygwin notifier, doing the initialization of the thread-local variables exactly the same as ... check-in: 57e106c650 user: jan.nijtmans tags: bug-5d170b5ca5
09:02
Merge trunk. Gustaf's latest and greatest fix. check-in: e2f25680d8 user: jan.nijtmans tags: bug-5d170b5ca5
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to unix/tclUnixNotfy.c.

99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
	 * that an event is ready to be processed
	 * by sending this event. */
    void *hwnd;			/* Messaging window. */
#else /* !__CYGWIN__ */
    pthread_cond_t waitCV;	/* Any other thread alerts a notifier that an
				 * event is ready to be processed by signaling
				 * this condition variable. */
    int waitCVinitialized;  /* Variable to flag initialization of the structure */
#endif /* __CYGWIN__ */

    int eventReady;		/* True if an event is ready to be processed.
				 * Used as condition flag together with waitCV
				 * above. */
#endif /* TCL_THREADS */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;







<

>







99
100
101
102
103
104
105

106
107
108
109
110
111
112
113
114
	 * that an event is ready to be processed
	 * by sending this event. */
    void *hwnd;			/* Messaging window. */
#else /* !__CYGWIN__ */
    pthread_cond_t waitCV;	/* Any other thread alerts a notifier that an
				 * event is ready to be processed by signaling
				 * this condition variable. */

#endif /* __CYGWIN__ */
    int waitCVinitialized;  /* Variable to flag initialization of the structure */
    int eventReady;		/* True if an event is ready to be processed.
				 * Used as condition flag together with waitCV
				 * above. */
#endif /* TCL_THREADS */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;
250
251
252
253
254
255
256
257
258
259

260
261
262
263
264
265
266
				    void *);
extern void __stdcall	PostQuitMessage(int);
extern void *__stdcall	RegisterClassW(const WNDCLASS *);
extern unsigned char __stdcall	ResetEvent(void *);
extern unsigned char __stdcall	TranslateMessage(const MSG *);

/*
 * Threaded-cygwin specific functions in this file:
 */


static DWORD __stdcall	NotifierProc(void *hwnd, unsigned int message,
			    void *wParam, void *lParam);
#endif /* TCL_THREADS && __CYGWIN__ */

#if TCL_THREADS
/*
 *----------------------------------------------------------------------







|


>







250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
				    void *);
extern void __stdcall	PostQuitMessage(int);
extern void *__stdcall	RegisterClassW(const WNDCLASS *);
extern unsigned char __stdcall	ResetEvent(void *);
extern unsigned char __stdcall	TranslateMessage(const MSG *);

/*
 * Threaded-cygwin specific constants and functions in this file:
 */

static const WCHAR NotfyClassName[] = L"TclNotifier";
static DWORD __stdcall	NotifierProc(void *hwnd, unsigned int message,
			    void *wParam, void *lParam);
#endif /* TCL_THREADS && __CYGWIN__ */

#if TCL_THREADS
/*
 *----------------------------------------------------------------------
327
328
329
330
331
332
333
334
335
336
337
338





















339

340
341
342
343
344
345
346
347
348
349
	return tclNotifierHooks.initNotifierProc();
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

#ifdef TCL_THREADS
	tsdPtr->eventReady = 0;

#ifndef __CYGWIN__
	/*
	 * Initialize thread specific condition variable for this thread.
	 */
	if (tsdPtr->waitCVinitialized == 0) {





















	    pthread_cond_init(&tsdPtr->waitCV, NULL);

	    tsdPtr->waitCVinitialized = 1;
	}
#endif

	pthread_mutex_lock(&notifierInitMutex);
#if defined(HAVE_PTHREAD_ATFORK) && !defined(__APPLE__) && !defined(__hpux)
	/*
	 * Install pthread_atfork handlers to clean up the notifier in the
	 * child of a fork.
	 */







<




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>


<







328
329
330
331
332
333
334

335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
	return tclNotifierHooks.initNotifierProc();
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

#ifdef TCL_THREADS
	tsdPtr->eventReady = 0;


	/*
	 * Initialize thread specific condition variable for this thread.
	 */
	if (tsdPtr->waitCVinitialized == 0) {
#ifdef __CYGWIN__
	    WNDCLASS class;

	    class.style = 0;
	    class.cbClsExtra = 0;
	    class.cbWndExtra = 0;
	    class.hInstance = TclWinGetTclInstance();
	    class.hbrBackground = NULL;
	    class.lpszMenuName = NULL;
	    class.lpszClassName = NotfyClassName;
	    class.lpfnWndProc = NotifierProc;
	    class.hIcon = NULL;
	    class.hCursor = NULL;

	    RegisterClassW(&class);
	    tsdPtr->hwnd = CreateWindowExW(NULL, class.lpszClassName,
		    class.lpszClassName, 0, 0, 0, 0, 0, NULL, NULL,
		    TclWinGetTclInstance(), NULL);
	    tsdPtr->event = CreateEventW(NULL, 1 /* manual */,
		    0 /* !signaled */, NULL);
#else
	    pthread_cond_init(&tsdPtr->waitCV, NULL);
#endif /* __CYGWIN */
	    tsdPtr->waitCVinitialized = 1;
	}


	pthread_mutex_lock(&notifierInitMutex);
#if defined(HAVE_PTHREAD_ATFORK) && !defined(__APPLE__) && !defined(__hpux)
	/*
	 * Install pthread_atfork handlers to clean up the notifier in the
	 * child of a fork.
	 */
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
	pthread_mutex_lock(&notifierInitMutex);
	notifierCount--;

	/*
	 * Check if FinializeNotifier was called without a prior InitNotifier
	 * in this thread.
	 */
#ifndef __CYGWIN__
	assert(tsdPtr->waitCVinitialized == 1);
#endif

	/*
	 * If this is the last thread to use the notifier, close the notifier
	 * pipe and wait for the background thread to terminate.
	 */

	if (notifierCount == 0) {







<

<







420
421
422
423
424
425
426

427

428
429
430
431
432
433
434
	pthread_mutex_lock(&notifierInitMutex);
	notifierCount--;

	/*
	 * Check if FinializeNotifier was called without a prior InitNotifier
	 * in this thread.
	 */

	assert(tsdPtr->waitCVinitialized == 1);


	/*
	 * If this is the last thread to use the notifier, close the notifier
	 * pipe and wait for the background thread to terminate.
	 */

	if (notifierCount == 0) {
436
437
438
439
440
441
442

443
444
445
446

447
448
449
450
451
452
453
	}

	/*
	 * Clean up any synchronization objects in the thread local storage.
	 */

#ifdef __CYGWIN__

	CloseHandle(tsdPtr->event);
#else /* __CYGWIN__ */
	pthread_cond_destroy(&tsdPtr->waitCV);
#endif /* __CYGWIN__ */


	pthread_mutex_unlock(&notifierInitMutex);
#endif /* TCL_THREADS */
    }
}

/*







>




>







455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
	}

	/*
	 * Clean up any synchronization objects in the thread local storage.
	 */

#ifdef __CYGWIN__
	DestroyWindow(tsdPtr->hwnd);
	CloseHandle(tsdPtr->event);
#else /* __CYGWIN__ */
	pthread_cond_destroy(&tsdPtr->waitCV);
#endif /* __CYGWIN__ */
	tsdPtr->waitCVinitialized = 0;

	pthread_mutex_unlock(&notifierInitMutex);
#endif /* TCL_THREADS */
    }
}

/*
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	FileHandler *filePtr;

	/*
	 * Check if InitNotifier was called before in this thread
	 */
#ifndef __CYGWIN__
	assert(tsdPtr->waitCVinitialized == 1);
#endif
	for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
		filePtr = filePtr->nextPtr) {
	    if (filePtr->fd == fd) {
		break;
	    }
	}
	if (filePtr == NULL) {







<

<







612
613
614
615
616
617
618

619

620
621
622
623
624
625
626
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	FileHandler *filePtr;

	/*
	 * Check if InitNotifier was called before in this thread
	 */

	assert(tsdPtr->waitCVinitialized == 1);

	for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
		filePtr = filePtr->nextPtr) {
	    if (filePtr->fd == fd) {
		break;
	    }
	}
	if (filePtr == NULL) {
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
	FileHandler *filePtr, *prevPtr;
	int i;
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	/*
	 * Check if InitNotifier was called before in this thread
	 */
#ifndef __CYGWIN__
	assert(tsdPtr->waitCVinitialized == 1);
#endif

	/*
	 * Find the entry for the given file (and return if there isn't one).
	 */

	for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
		prevPtr = filePtr, filePtr = filePtr->nextPtr) {







<

<







687
688
689
690
691
692
693

694

695
696
697
698
699
700
701
	FileHandler *filePtr, *prevPtr;
	int i;
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	/*
	 * Check if InitNotifier was called before in this thread
	 */

	assert(tsdPtr->waitCVinitialized == 1);


	/*
	 * Find the entry for the given file (and return if there isn't one).
	 */

	for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
		prevPtr = filePtr, filePtr = filePtr->nextPtr) {
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
     */

    tsdPtr = TCL_TSD_INIT(&dataKey);

    /*
     * Check if InitNotifier was called before in this thread
     */
#ifndef __CYGWIN__
    assert(tsdPtr->waitCVinitialized == 1);
#endif

    for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
	    filePtr = filePtr->nextPtr) {
	if (filePtr->fd != fileEvPtr->fd) {
	    continue;
	}








<

<







797
798
799
800
801
802
803

804

805
806
807
808
809
810
811
     */

    tsdPtr = TCL_TSD_INIT(&dataKey);

    /*
     * Check if InitNotifier was called before in this thread
     */

    assert(tsdPtr->waitCVinitialized == 1);


    for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
	    filePtr = filePtr->nextPtr) {
	if (filePtr->fd != fileEvPtr->fd) {
	    continue;
	}

885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
	int numFound;
#endif /* TCL_THREADS */
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	/*
	 *  Check if InitNotifier was called before in this thread
	 */
#ifndef __CYGWIN__
	assert(tsdPtr->waitCVinitialized == 1);
#endif

	/*
	 * Set up the timeout structure. Note that if there are no events to
	 * check for, we return with a negative result rather than blocking
	 * forever.
	 */








<

<







900
901
902
903
904
905
906

907

908
909
910
911
912
913
914
	int numFound;
#endif /* TCL_THREADS */
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	/*
	 *  Check if InitNotifier was called before in this thread
	 */

	assert(tsdPtr->waitCVinitialized == 1);


	/*
	 * Set up the timeout structure. Note that if there are no events to
	 * check for, we return with a negative result rather than blocking
	 * forever.
	 */

934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
	/*
	 * Start notifier thread and place this thread on the list of
	 * interested threads, signal the notifier thread, and wait for a
	 * response or a timeout.
	 */
	StartNotifierThread();

#ifdef __CYGWIN__
	if (!tsdPtr->hwnd) {
	    WNDCLASS class;

	    class.style = 0;
	    class.cbClsExtra = 0;
	    class.cbWndExtra = 0;
	    class.hInstance = TclWinGetTclInstance();
	    class.hbrBackground = NULL;
	    class.lpszMenuName = NULL;
	    class.lpszClassName = L"TclNotifier";
	    class.lpfnWndProc = NotifierProc;
	    class.hIcon = NULL;
	    class.hCursor = NULL;

	    RegisterClassW(&class);
	    tsdPtr->hwnd = CreateWindowExW(NULL, class.lpszClassName,
		    class.lpszClassName, 0, 0, 0, 0, 0, NULL, NULL,
		    TclWinGetTclInstance(), NULL);
	    tsdPtr->event = CreateEventW(NULL, 1 /* manual */,
		    0 /* !signaled */, NULL);
	}
#endif /* __CYGWIN */

	pthread_mutex_lock(&notifierMutex);

	if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0
#if defined(__APPLE__) && defined(__LP64__)
		/*
		 * On 64-bit Darwin, pthread_cond_timedwait() appears to have
		 * a bug that causes it to wait forever when passed an







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







947
948
949
950
951
952
953
























954
955
956
957
958
959
960
	/*
	 * Start notifier thread and place this thread on the list of
	 * interested threads, signal the notifier thread, and wait for a
	 * response or a timeout.
	 */
	StartNotifierThread();

























	pthread_mutex_lock(&notifierMutex);

	if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0
#if defined(__APPLE__) && defined(__LP64__)
		/*
		 * On 64-bit Darwin, pthread_cond_timedwait() appears to have
		 * a bug that causes it to wait forever when passed an
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491

1492



1493

1494
1495
1496
1497
1498
1499
1500
     * waitingListPtr != 0: there are threads currently waiting for events.
     */

    if (atForkInit == 1) {

	notifierCount = 0;
	if (notifierThreadRunning == 1) {
#ifndef __CYGWIN__
	    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#endif
	    notifierThreadRunning = 0;

	    close(triggerPipe);
	    triggerPipe = -1;
	    /*
	     * The waitingListPtr might contain event info from multiple
	     * threads, which are invalid here, so setting it to NULL is not
	     * unreasonable.
	     */
	    waitingListPtr = NULL;

	    /*
	     * The tsdPtr from before the fork is copied as well.  But since
	     * we are paranoic, we don't trust its condvar and reset it.
	     */

#ifndef __CYGWIN__



	    assert(tsdPtr->waitCVinitialized == 1);

	    pthread_cond_destroy(&tsdPtr->waitCV);
	    pthread_cond_init(&tsdPtr->waitCV, NULL);
#endif
	    /*
	     * The list of registered event handlers at fork time is in
	     * tsdPtr->firstFileHandlerPtr;
	     */







<

<















>
|
>
>
>
|
>







1456
1457
1458
1459
1460
1461
1462

1463

1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
     * waitingListPtr != 0: there are threads currently waiting for events.
     */

    if (atForkInit == 1) {

	notifierCount = 0;
	if (notifierThreadRunning == 1) {

	    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	    notifierThreadRunning = 0;

	    close(triggerPipe);
	    triggerPipe = -1;
	    /*
	     * The waitingListPtr might contain event info from multiple
	     * threads, which are invalid here, so setting it to NULL is not
	     * unreasonable.
	     */
	    waitingListPtr = NULL;

	    /*
	     * The tsdPtr from before the fork is copied as well.  But since
	     * we are paranoic, we don't trust its condvar and reset it.
	     */
	    assert(tsdPtr->waitCVinitialized == 1);
#ifdef __CYGWIN__
	    tsdPtr->hwnd = CreateWindowExW(NULL, NotfyClassName,
		    NotfyClassName, 0, 0, 0, 0, 0, NULL, NULL,
		    TclWinGetTclInstance(), NULL);
	    ResetEvent(tsdPtr->event);
#else
	    pthread_cond_destroy(&tsdPtr->waitCV);
	    pthread_cond_init(&tsdPtr->waitCV, NULL);
#endif
	    /*
	     * The list of registered event handlers at fork time is in
	     * tsdPtr->firstFileHandlerPtr;
	     */