Diff
Not logged in

Differences From Artifact [f88b2e9526]:

To Artifact [4e48cb7a1b]:


1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







/*
 * tclWinSock.c --
 *
 *	This file contains Windows-specific socket related code.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinSock.c,v 1.51 2005/12/13 22:43:18 kennykb Exp $
 * RCS: @(#) $Id: tclWinSock.c,v 1.52 2006/03/10 17:34:35 vasiljevic Exp $
 */

#include "tclWinInt.h"

/*
 * Make sure to remove the redirection defines set in tclWinPort.h that is in
 * use in other sections of the core, except for us.
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
245
246
247
248
249
250
251

252
253
254
255
256
257
258







-







static DWORD WINAPI	SocketThread(LPVOID arg);
static void		TcpThreadActionProc(ClientData instanceData,
			    int action);

static Tcl_EventCheckProc	SocketCheckProc;
static Tcl_EventProc		SocketEventProc;
static Tcl_EventSetupProc	SocketSetupProc;
static Tcl_ExitProc		SocketThreadExitHandler;
static Tcl_DriverBlockModeProc	TcpBlockProc;
static Tcl_DriverCloseProc	TcpCloseProc;
static Tcl_DriverSetOptionProc	TcpSetOptionProc;
static Tcl_DriverGetOptionProc	TcpGetOptionProc;
static Tcl_DriverInputProc	TcpInputProc;
static Tcl_DriverOutputProc	TcpOutputProc;
static Tcl_DriverWatchProc	TcpWatchProc;
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301







-
+







 *
 * InitSockets --
 *
 *	Initialize the socket module. Attempts to load the wsock32.dll library
 *	and set up the winSock function table. If successful, registers the
 *	event window for the socket notifier code.
 *
 *	Assumes Mutex is held.
 *	Assumes socketMutex is held.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Dynamically loads wsock32.dll, and registers a new window class and
 *	creates a window for use in asynchronous socket notification.
473
474
475
476
477
478
479
480

481
482

483
484



485



486
487
488
489
490
491
492
493

494
495
496
497


498
499
500

501
502

503
504
505

506
507
508
509
510
511
512
513
514
515

516
517
518
519
520
521
522
523
472
473
474
475
476
477
478

479


480

481
482
483
484
485
486
487
488
489
490


491
492
493
494
495
496
497


498
499
500
501

502


503

504

505
506
507
508

509
510
511
512


513

514
515
516
517
518
519
520







-
+
-
-
+
-

+
+
+

+
+
+


-
-




+


-
-
+
+


-
+
-
-
+
-

-
+



-




-
-
+
-







    /*
     * Check for per-thread initialization.
     */

    if (tsdPtr == NULL) {
	tsdPtr = TCL_TSD_INIT(&dataKey);
	tsdPtr->socketList = NULL;
	tsdPtr->hwnd = NULL;
	tsdPtr->hwnd       = NULL;

	tsdPtr->threadId = Tcl_GetCurrentThread();
	tsdPtr->threadId   = Tcl_GetCurrentThread();

	tsdPtr->readyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	if (tsdPtr->readyEvent == NULL) {
	    goto unloadLibrary;
	}
	tsdPtr->socketListLock = CreateEvent(NULL, FALSE, TRUE, NULL);
	if (tsdPtr->socketListLock == NULL) {
	    goto unloadLibrary;
	}
	tsdPtr->socketThread = CreateThread(NULL, 256, SocketThread,
		tsdPtr, 0, &id);
	SetThreadPriority(tsdPtr->socketThread, THREAD_PRIORITY_HIGHEST);

	if (tsdPtr->socketThread == NULL) {
	    goto unloadLibrary;
	}

	SetThreadPriority(tsdPtr->socketThread, THREAD_PRIORITY_HIGHEST);

	/*
	 * Wait for the thread to signal that the window has been created and
	 * is ready to go. Timeout after twenty seconds.
	 * Wait for the thread to signal when the window has
	 * been created and if it is ready to go.
	 */

	if (WaitForSingleObject(tsdPtr->readyEvent, 20000) == WAIT_TIMEOUT) {
	WaitForSingleObject(tsdPtr->readyEvent, INFINITE);
	    goto unloadLibrary;
	}


	if (tsdPtr->hwnd == NULL) {
	    goto unloadLibrary;
	    goto unloadLibrary; /* Trouble creating the window */
	}

	Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL);
	Tcl_CreateThreadExitHandler(SocketThreadExitHandler, NULL);
    }
    return;

  unloadLibrary:
    if (tsdPtr != NULL && tsdPtr->hwnd != NULL) {
	SocketThreadExitHandler(0);
    TclpFinalizeSockets();
    }
    FreeLibrary(winSock.hModule);
    winSock.hModule = NULL;
    return;
}

/*
 *----------------------------------------------------------------------
567
568
569
570
571
572
573

574
575
576
577
578
579

580
581
582
583
584
585
586
587
588
589
590
591
592

593



594

595
596
597
598
599
600
601

602
603
604
605
606
607
608


609
610
611

612
613

614

615
616
617
618
619



620
621
622
623



624
625
626

627
628
629
630
631
632
633
634














635
636
637
638
639
640
641
642
564
565
566
567
568
569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
584
585
586
587
588
589

590
591
592
593
594

595

596
597
598
599
600

601
602
603
604
605



606
607

608

609

610
611

612





613
614
615




616
617
618



619








620
621
622
623
624
625
626
627
628
629
630
631
632
633

634
635
636
637
638
639
640







+





-
+












-
+

+
+
+
-
+
-





-
+




-
-
-
+
+
-

-
+
-

+
-
+
-
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-







    /* ARGSUSED */
static void
SocketExitHandler(
    ClientData clientData)		/* Not used. */
{
    Tcl_MutexLock(&socketMutex);
    if (winSock.hModule) {

	/*
	 * Make sure the socket event handling window is cleaned-up for, at
	 * most, this thread.
	 */

	SocketThreadExitHandler(clientData);
	TclpFinalizeSockets();
	UnregisterClass("TclSocket", TclWinGetTclInstance());
	winSock.WSACleanup();
	FreeLibrary(winSock.hModule);
	winSock.hModule = NULL;
    }
    initialized = 0;
    Tcl_MutexUnlock(&socketMutex);
}

/*
 *----------------------------------------------------------------------
 *
 * SocketThreadExitHandler --
 * TclpFinalizeSockets --
 *
 *	This function is called from Tcl_FinalizeThread to finalize
 *	the platform specific socket subsystem.
 *	Also, it may be called from within this module to cleanup
 *	Callback invoked during thread clean up to delete the socket event
 *	the state if unable to initialize the sockets subsystem.
 *	source.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Delete the event source.
 *	Deletes the event source and destroys the socket thread.
 *
 *----------------------------------------------------------------------
 */

    /* ARGSUSED */
static void
SocketThreadExitHandler(
void
TclpFinalizeSockets()
    ClientData clientData)	/* Not used. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr;
	(ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);

    tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
    if (tsdPtr != NULL && tsdPtr->socketThread != NULL) {
    if (tsdPtr != NULL) {
	DWORD exitCode;

	GetExitCodeThread(tsdPtr->socketThread, &exitCode);
	if (exitCode == STILL_ACTIVE) {
	    PostMessage(tsdPtr->hwnd, SOCKET_TERMINATE, 0, 0);
	if (tsdPtr->socketThread != NULL) {
	    if (tsdPtr->hwnd != NULL) {
		PostMessage(tsdPtr->hwnd, SOCKET_TERMINATE, 0, 0);

	    /*
	     * Wait for the thread to close. This ensures that we are
	     * completely cleaned up before we leave this function. If
		/*
		 * Wait for the thread to exit. This ensures that we are
		 * completely cleaned up before we leave this function.
	     * Tcl_Finalize was called from DllMain, the thread is in a paused
	     * state so we need to timeout and continue.
	     */
		 */

	    WaitForSingleObject(tsdPtr->socketThread, 100);
	}
	CloseHandle(tsdPtr->socketThread);
	tsdPtr->socketThread = NULL;
	CloseHandle(tsdPtr->readyEvent);
	CloseHandle(tsdPtr->socketListLock);

		WaitForSingleObject(tsdPtr->readyEvent, INFINITE);
		tsdPtr->hwnd = NULL;
	    }
	    CloseHandle(tsdPtr->socketThread);
	    tsdPtr->socketThread = NULL;
	}
	if (tsdPtr->readyEvent != NULL) {
	    CloseHandle(tsdPtr->readyEvent);
	    tsdPtr->readyEvent = NULL;
	}
	if (tsdPtr->socketListLock != NULL) {
	    CloseHandle(tsdPtr->socketListLock);
	    tsdPtr->socketListLock = NULL;
	}
	Tcl_DeleteThreadExitHandler(SocketThreadExitHandler, NULL);
	Tcl_DeleteEventSource(SocketSetupProc, SocketCheckProc, NULL);
    }
}

/*
 *----------------------------------------------------------------------
 *
2301
2302
2303
2304
2305
2306
2307




2308
2309
2310
2311
2312
2313

2314
2315
2316
2317




2318
2319
2320
2321
2322
2323


2324
2325
2326
2327
2328
2329






2330
2331
2332
2333
2334
2335
2336
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313


2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349







+
+
+
+




-
-
+




+
+
+
+






+
+






+
+
+
+
+
+







static DWORD WINAPI
SocketThread(
    LPVOID arg)
{
    MSG msg;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)(arg);

    /*
     * Create a dummy window receiving socket events.
     */

    tsdPtr->hwnd = CreateWindow("TclSocket", "TclSocket",
	    WS_TILED, 0, 0, 0, 0, NULL, NULL, windowClass.hInstance, arg);

    /*
     * Signal the main thread that the window has been created and that the
     * socket thread is ready to go.
     * Signalize thread creator that we are done creating the window.
     */

    SetEvent(tsdPtr->readyEvent);

    /*
     * If unable to create the window, exit this thread immediately.
     */

    if (tsdPtr->hwnd == NULL) {
	return 1;
    }

    /*
     * Process all messages on the socket window until WM_QUIT.
     * This threads exits only when instructed to do so by the
     * call to PostMessage(SOCKET_TERMINATE) in TclpFinalizeSockets().
     */

    while (GetMessage(&msg, NULL, 0, 0) > 0) {
	DispatchMessage(&msg);
    }

    /*
     * This releases waiters on thread exit in TclpFinalizeSockets()
     */

    SetEvent(tsdPtr->readyEvent);

    return msg.wParam;
}


/*
 *----------------------------------------------------------------------
 *
2700
2701
2702
2703
2704
2705
2706
2707

2708
2709
2710
2711
2712
2713
2714
2715
2716

2717
2718
2719
2720
2721
2722
2723
2713
2714
2715
2716
2717
2718
2719

2720
2721
2722
2723
2724
2725
2726
2727
2728

2729
2730
2731
2732
2733
2734
2735
2736







-
+








-
+







	SetEvent(tsdPtr->socketListLock);

	notifyCmd = SELECT;
    } else {
	SocketInfo **nextPtrPtr;
	int removed = 0;

	tsdPtr	= TCL_TSD_INIT(&dataKey);
	tsdPtr = TCL_TSD_INIT(&dataKey);

	/*
	 * TIP #218, Bugfix: All access to socketList has to be protected by
	 * the lock.
	 */

	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
	for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL;
	     nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
		nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
	    if ((*nextPtrPtr) == infoPtr) {
		(*nextPtrPtr) = infoPtr->nextPtr;
		removed = 1;
		break;
	    }
	}
	SetEvent(tsdPtr->socketListLock);