Changes On Branch a201b97b3e52c94c
Not logged in

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

Changes In Branch rfe-notifier-fork Through [a201b97b3e] Excluding Merge-Ins

This is equivalent to a diff from 728fb2f25b to a201b97b3e

2013-07-23
09:07
Add "testfork" test command. Not used in any test-case yet check-in: b425245964 user: jan.nijtmans tags: core-8-5-branch
2013-07-22
10:57
Use pthread_atfork() when available. check-in: 94b207274c user: jan.nijtmans tags: rfe-notifier-fork
10:11
Test-case should pass on Darwin or with non-threaded build as well. check-in: a201b97b3e user: jan.nijtmans tags: rfe-notifier-fork
10:10
Fix bug which hangs iocmd.tf-32.1 check-in: 9ce264b926 user: jan.nijtmans tags: rfe-notifier-fork
2013-07-21
14:52
Rebase to core-8-5-branch Add "testfork" test command to be usable in testcase. check-in: 6f69bbba43 user: jan.nijtmans tags: rfe-notifier-fork
2013-07-08
18:56
Unbreak MSVC6 debug build (thanks Andreas Kupries!) check-in: d369017148 user: jan.nijtmans tags: trunk
18:55
Unbreak MSVC6 debug build (thanks Andreas Kupries!) check-in: 728fb2f25b user: jan.nijtmans tags: core-8-5-branch
06:49
Build stub objects with -DSTATIC_BUILD on all platforms. Only important on win32 (already done) and ... check-in: dda8563eba user: jan.nijtmans tags: core-8-5-branch

Changes to ChangeLog.






1
2
3
4
5
6
7






2013-07-05  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Africa/Casablanca:
	* library/tzdata/America/Asuncion:
	* library/tzdata/Antarctica/Macquarie:
	* library/tzdata/Asia/Gaza:
	* library/tzdata/Asia/Hebron:
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
2013-07-17  Harald Oehlmann  <oehhar@users.sf.net>

	* tclUnixNotify.c Tcl_InitNotifier: RFE [a0bc856dcd]
	  Start notifier thread again if we were forked, to solve Rivet bug
	  55153.

2013-07-05  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Africa/Casablanca:
	* library/tzdata/America/Asuncion:
	* library/tzdata/Antarctica/Macquarie:
	* library/tzdata/Asia/Gaza:
	* library/tzdata/Asia/Hebron:
Added tests/unixForkEvent.test.


























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# This file contains a collection of tests for the procedures in the file
# tclUnixNotify.c.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2
namespace import -force ::tcltest::*

testConstraint testfork [llength [info commands testfork]]

# Test if the notifier thread is well initialized in a forked interpreter
# by Tcl_InitNotifier
test unixforkevent-1.1 {fork and test writeable event} \
    -constraints testfork \
    -body {
	set folder [makeDirectory unixtestfork]
	set pid [testfork]
	if {$pid == 0} {
	    # we are the forked process
	    set result initialized
	    set h [open [file join $folder test.txt] w]
	    fileevent $h writable\
		    "set result writable;\
		    after cancel [after 1000 {set result timeout}]"
	    vwait result
	    close $h
	    makeFile $result result.txt $folder
	    exit
	}
	# we are the original process
	while {![file readable [file join $folder result.txt]]} {}
	viewFile result.txt $folder
    } \
    -result {writable} \
    -cleanup { 
	catch { removeFolder $folder }
    }

::tcltest::cleanupTests
return
Changes to unix/tclUnixNotfy.c.
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129









130
131
132
133
134
135
136
    Tcl_Condition waitCV;	/* Any other thread alerts a notifier that an
				 * event is ready to be processed by signaling
				 * this condition variable. */
#endif /* __CYGWIN__ */
    int eventReady;		/* True if an event is ready to be processed.
				 * Used as condition flag together with waitCV
				 * above. */
#endif
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;

#ifdef TCL_THREADS
/*
 * The following static indicates the number of threads that have initialized
 * notifiers.
 *
 * You must hold the notifierMutex lock before accessing this variable.
 */

static int notifierCount = 0;










/*
 * The following variable points to the head of a doubly-linked list of
 * ThreadSpecificData structures for all threads that are currently waiting on
 * an event.
 *
 * You must hold the notifierMutex lock before accessing this list.
 */







|














>
>
>
>
>
>
>
>
>







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
    Tcl_Condition waitCV;	/* Any other thread alerts a notifier that an
				 * event is ready to be processed by signaling
				 * this condition variable. */
#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;

#ifdef TCL_THREADS
/*
 * The following static indicates the number of threads that have initialized
 * notifiers.
 *
 * You must hold the notifierMutex lock before accessing this variable.
 */

static int notifierCount = 0;

/*
 * The following static stores the process ID of the initialized notifier
 * thread. If it changes, we have passed a fork and we should start a new
 * notifier thread.
 *
 * You must hold the notifierMutex lock before accessing this variable.
 */
static pid_t processIDInitialized = 0;

/*
 * The following variable points to the head of a doubly-linked list of
 * ThreadSpecificData structures for all threads that are currently waiting on
 * an event.
 *
 * You must hold the notifierMutex lock before accessing this list.
 */
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

/*
 * This is the thread ID of the notifier thread that does select.
 */

static Tcl_ThreadId notifierThread;

#endif

/*
 * Static routines defined in this file.
 */

#ifdef TCL_THREADS
static void	NotifierThreadProc(ClientData clientData);







|







190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

/*
 * This is the thread ID of the notifier thread that does select.
 */

static Tcl_ThreadId notifierThread;

#endif /* TCL_THREADS */

/*
 * Static routines defined in this file.
 */

#ifdef TCL_THREADS
static void	NotifierThreadProc(ClientData clientData);
263
264
265
266
267
268
269











270
271
272
273
274

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
    tsdPtr->eventReady = 0;

    /*
     * Start the Notifier thread if necessary.
     */

    Tcl_MutexLock(&notifierMutex);











    if (notifierCount == 0) {
	if (TclpThreadCreate(&notifierThread, NotifierThreadProc, NULL,
		TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) {
	    Tcl_Panic("Tcl_InitNotifier: unable to start notifier thread");
	}

    }
    notifierCount++;

    /*
     * Wait for the notifier pipe to be created.
     */

    while (triggerPipe < 0) {
	Tcl_ConditionWait(&notifierCV, &notifierMutex, NULL);
    }

    Tcl_MutexUnlock(&notifierMutex);
#endif
    return (ClientData) tsdPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FinalizeNotifier --







>
>
>
>
>
>
>
>
>
>
>





>












|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
    tsdPtr->eventReady = 0;

    /*
     * Start the Notifier thread if necessary.
     */

    Tcl_MutexLock(&notifierMutex);
    /*
     * Check if my process id changed, e.g. I was forked
     * In this case, restart the notifier thread and close the
     * pipe to the original notifier thread
     */
    if (notifierCount > 0 && processIDInitialized != getpid()) {
	notifierCount = 0;
	processIDInitialized = 0;
	close(triggerPipe);
	triggerPipe = -1;
    }
    if (notifierCount == 0) {
	if (TclpThreadCreate(&notifierThread, NotifierThreadProc, NULL,
		TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) {
	    Tcl_Panic("Tcl_InitNotifier: unable to start notifier thread");
	}
    processIDInitialized = getpid();
    }
    notifierCount++;

    /*
     * Wait for the notifier pipe to be created.
     */

    while (triggerPipe < 0) {
	Tcl_ConditionWait(&notifierCV, &notifierMutex, NULL);
    }

    Tcl_MutexUnlock(&notifierMutex);
#endif /* TCL_THREADS */
    return (ClientData) tsdPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FinalizeNotifier --
Changes to unix/tclUnixTest.c.
62
63
64
65
66
67
68


69
70
71
72
73
74
75
static void		TestFileHandlerProc(ClientData clientData, int mask);
static int		TestfilehandlerCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, CONST char **argv);
static int		TestfilewaitCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, CONST char **argv);
static int		TestfindexecutableCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, CONST char **argv);


static int		TestgetopenfileCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, CONST char **argv);
static int		TestgetdefencdirCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, CONST char **argv);
static int		TestsetdefencdirCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, CONST char **argv);
int			TclplatformtestInit(Tcl_Interp *interp);







>
>







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
static void		TestFileHandlerProc(ClientData clientData, int mask);
static int		TestfilehandlerCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, CONST char **argv);
static int		TestfilewaitCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, CONST char **argv);
static int		TestfindexecutableCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, CONST char **argv);
static int		TestforkObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST *argv);
static int		TestgetopenfileCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, CONST char **argv);
static int		TestgetdefencdirCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, CONST char **argv);
static int		TestsetdefencdirCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, CONST char **argv);
int			TclplatformtestInit(Tcl_Interp *interp);
105
106
107
108
109
110
111


112
113
114
115
116
117
118
    Tcl_CreateCommand(interp, "testchmod", TestchmodCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testfilehandler", TestfilehandlerCmd,
            (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testfilewait", TestfilewaitCmd,
            (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testfindexecutable", TestfindexecutableCmd,


            (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testgetopenfile", TestgetopenfileCmd,
            (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testgetdefenc", TestgetdefencdirCmd,
            (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testsetdefenc", TestsetdefencdirCmd,
            (ClientData) 0, NULL);







>
>







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
    Tcl_CreateCommand(interp, "testchmod", TestchmodCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testfilehandler", TestfilehandlerCmd,
            (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testfilewait", TestfilewaitCmd,
            (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testfindexecutable", TestfindexecutableCmd,
            (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testfork", TestforkObjCmd,
            (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testgetopenfile", TestgetopenfileCmd,
            (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testgetdefenc", TestgetdefencdirCmd,
            (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testsetdefenc", TestsetdefencdirCmd,
            (ClientData) 0, NULL);
529
530
531
532
533
534
535











































536
537
538
539
540
541
542
                " defaultDir\"", NULL);
        return TCL_ERROR;
    }

    Tcl_SetDefaultEncodingDir(argv[1]);
    return TCL_OK;
}












































/*
 *----------------------------------------------------------------------
 *
 * TestgetdefencdirCmd --
 *
 *	This function implements the "testgetdefenc" command. It is used to







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







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
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
                " defaultDir\"", NULL);
        return TCL_ERROR;
    }

    Tcl_SetDefaultEncodingDir(argv[1]);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestforkObjCmd --
 *
 *	This function implements the "testfork" command. It is used to
 *	fork the Tcl process for specific test cases.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestforkObjCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST *objv)		/* Argument strings. */
{
    pid_t pid;

    if (objc != 1) {
        Tcl_WrongNumArgs(interp, 1, objv, "");
        return TCL_ERROR;
    }
    pid = fork();
    if (pid == -1) {
        Tcl_AppendResult(interp,
                "Cannot fork", NULL);
        return TCL_ERROR;
    }
    if (pid==0) {
	Tcl_InitNotifier();
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(pid));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestgetdefencdirCmd --
 *
 *	This function implements the "testgetdefenc" command. It is used to