Tcl Source Code

Check-in [bfddfa54a6]
Login

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

Overview
Comment:3532959 Make sure the lifetime management of entries in the linePBodyPtr hash table can tolerate either order of teardown, interp first, or Proc first.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: bfddfa54a63fbd2aac0266dc1a7657e95b46dba5
User & Date: dgp 2012-06-11 17:49:12
Context
2012-06-12
12:36
add test that triggered reporting of [Bug 3530230] check-in: 41bb6c4e84 user: dkf tags: trunk
2012-06-11
17:49
3532959 Make sure the lifetime management of entries in the linePBodyPtr hash table can tolerate eit... check-in: bfddfa54a6 user: dgp tags: trunk
17:34
3532959 Make sure the lifetime management of entries in the linePBodyPtr hash table can tolerate eit... check-in: 20de131aef user: dgp tags: core-8-5-branch
2012-06-08
13:25
3530533 Centralize #include <pthread.h> in the tclUnixPort.h header so that old unix systems that ne... check-in: a790f23b77 user: dgp tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.








1
2
3
4
5
6
7







2012-06-08  Don Porter  <[email protected]>

	* unix/configure.in:	Update autogoo for gettimeofday().
	* unix/tclUnixPort.h:	Thanks Joe English.
	* unix/configure:	autoconf 2.13

	* unix/tclUnixPort.h:	[Bug 3530533] Centralize #include <pthread.h>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
2012-06-11  Don Porter  <[email protected]>

	* generic/tclBasic.c:	[Bug 3532959] Make sure the lifetime management
	* generic/tclProc.c:	of entries in the linePBodyPtr hash table can
	* tests/proc.test:	tolerate either order of teardown, interp first,
	or Proc first.

2012-06-08  Don Porter  <[email protected]>

	* unix/configure.in:	Update autogoo for gettimeofday().
	* unix/tclUnixPort.h:	Thanks Joe English.
	* unix/configure:	autoconf 2.13

	* unix/tclUnixPort.h:	[Bug 3530533] Centralize #include <pthread.h>

Changes to generic/tclBasic.c.

1551
1552
1553
1554
1555
1556
1557

1558


1559
1560
1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
     * contents.
     */

    for (hPtr = Tcl_FirstHashEntry(iPtr->linePBodyPtr, &search);
	    hPtr != NULL;
	    hPtr = Tcl_NextHashEntry(&search)) {
	CmdFrame *cfPtr = Tcl_GetHashValue(hPtr);




	if (cfPtr->type == TCL_LOCATION_SOURCE) {
	    Tcl_DecrRefCount(cfPtr->data.eval.path);
	}
	ckfree(cfPtr->line);
	ckfree(cfPtr);

	Tcl_DeleteHashEntry(hPtr);
    }
    Tcl_DeleteHashTable(iPtr->linePBodyPtr);
    ckfree(iPtr->linePBodyPtr);
    iPtr->linePBodyPtr = NULL;

    /*







>

>
>
|
|
|
|
|
>







1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
     * contents.
     */

    for (hPtr = Tcl_FirstHashEntry(iPtr->linePBodyPtr, &search);
	    hPtr != NULL;
	    hPtr = Tcl_NextHashEntry(&search)) {
	CmdFrame *cfPtr = Tcl_GetHashValue(hPtr);
	Proc *procPtr = (Proc *) Tcl_GetHashKey(iPtr->linePBodyPtr, hPtr);

	procPtr->iPtr = NULL;
	if (cfPtr) {
	    if (cfPtr->type == TCL_LOCATION_SOURCE) {
		Tcl_DecrRefCount(cfPtr->data.eval.path);
	    }
	    ckfree(cfPtr->line);
	    ckfree(cfPtr);
	}
	Tcl_DeleteHashEntry(hPtr);
    }
    Tcl_DeleteHashTable(iPtr->linePBodyPtr);
    ckfree(iPtr->linePBodyPtr);
    iPtr->linePBodyPtr = NULL;

    /*

Changes to generic/tclProc.c.

2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247

2248
2249
2250
2251
2252
2253
2254

2255
2256
2257
2258
2259
2260
2261

    /*
     * TIP #280: Release the location data associated with this Proc
     * structure, if any. The interpreter may not exist (For example for
     * procbody structures created by tbcload.
     */

    if (!iPtr) {
	return;
    }

    hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, (char *) procPtr);
    if (!hePtr) {
	return;
    }

    cfPtr = Tcl_GetHashValue(hePtr);


    if (cfPtr->type == TCL_LOCATION_SOURCE) {
	Tcl_DecrRefCount(cfPtr->data.eval.path);
	cfPtr->data.eval.path = NULL;
    }
    ckfree(cfPtr->line);
    cfPtr->line = NULL;
    ckfree(cfPtr);

    Tcl_DeleteHashEntry(hePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TclUpdateReturnInfo --







|










>
|
|
|
|
|
|
|
>







2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263

    /*
     * TIP #280: Release the location data associated with this Proc
     * structure, if any. The interpreter may not exist (For example for
     * procbody structures created by tbcload.
     */

    if (iPtr == NULL) {
	return;
    }

    hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, (char *) procPtr);
    if (!hePtr) {
	return;
    }

    cfPtr = Tcl_GetHashValue(hePtr);

    if (cfPtr) {
	if (cfPtr->type == TCL_LOCATION_SOURCE) {
	    Tcl_DecrRefCount(cfPtr->data.eval.path);
	    cfPtr->data.eval.path = NULL;
	}
	ckfree(cfPtr->line);
	cfPtr->line = NULL;
	ckfree(cfPtr);
    }
    Tcl_DeleteHashEntry(hePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TclUpdateReturnInfo --
2479
2480
2481
2482
2483
2484
2485
2486

2487
2488
2489
2490
2491
2492
2493
SetLambdaFromAny(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    register Tcl_Obj *objPtr)	/* The object to convert. */
{
    Interp *iPtr = (Interp *) interp;
    const char *name;
    Tcl_Obj *argsPtr, *bodyPtr, *nsObjPtr, **objv;
    int objc, result;

    Proc *procPtr;

    if (interp == NULL) {
	return TCL_ERROR;
    }

    /*







|
>







2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
SetLambdaFromAny(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    register Tcl_Obj *objPtr)	/* The object to convert. */
{
    Interp *iPtr = (Interp *) interp;
    const char *name;
    Tcl_Obj *argsPtr, *bodyPtr, *nsObjPtr, **objv;
    int isNew, objc, result;
    CmdFrame *cfPtr = NULL;
    Proc *procPtr;

    if (interp == NULL) {
	return TCL_ERROR;
    }

    /*
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588

2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617


2618
2619
2620
2621
2622
2623
2624
	    /*
	     * We can record source location within a lambda only if the body
	     * was not created by substitution.
	     */

	    if (contextPtr->line
		    && (contextPtr->nline >= 2) && (contextPtr->line[1] >= 0)) {
		int isNew, buf[2];
		CmdFrame *cfPtr = ckalloc(sizeof(CmdFrame));

		/*
		 * Move from approximation (line of list cmd word) to actual
		 * location (line of 2nd list element).
		 */


		TclListLines(objPtr, contextPtr->line[1], 2, buf, NULL);

		cfPtr->level = -1;
		cfPtr->type = contextPtr->type;
		cfPtr->line = ckalloc(sizeof(int));
		cfPtr->line[0] = buf[1];
		cfPtr->nline = 1;
		cfPtr->framePtr = NULL;
		cfPtr->nextPtr = NULL;

		cfPtr->data.eval.path = contextPtr->data.eval.path;
		Tcl_IncrRefCount(cfPtr->data.eval.path);

		cfPtr->cmd.str.cmd = NULL;
		cfPtr->cmd.str.len = 0;

		Tcl_SetHashValue(Tcl_CreateHashEntry(iPtr->linePBodyPtr,
			procPtr, &isNew), cfPtr);
	    }

	    /*
	     * 'contextPtr' is going out of scope. Release the reference that
	     * it's holding to the source file path
	     */

	    Tcl_DecrRefCount(contextPtr->data.eval.path);
	}
	TclStackFree(interp, contextPtr);
    }



    /*
     * Set the namespace for this lambda: given by objv[2] understood as a
     * global reference, or else global per default.
     */

    if (objc == 2) {







|
<






>















<
<
<











>
>







2577
2578
2579
2580
2581
2582
2583
2584

2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606



2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
	    /*
	     * We can record source location within a lambda only if the body
	     * was not created by substitution.
	     */

	    if (contextPtr->line
		    && (contextPtr->nline >= 2) && (contextPtr->line[1] >= 0)) {
		int buf[2];


		/*
		 * Move from approximation (line of list cmd word) to actual
		 * location (line of 2nd list element).
		 */

		cfPtr = ckalloc(sizeof(CmdFrame));
		TclListLines(objPtr, contextPtr->line[1], 2, buf, NULL);

		cfPtr->level = -1;
		cfPtr->type = contextPtr->type;
		cfPtr->line = ckalloc(sizeof(int));
		cfPtr->line[0] = buf[1];
		cfPtr->nline = 1;
		cfPtr->framePtr = NULL;
		cfPtr->nextPtr = NULL;

		cfPtr->data.eval.path = contextPtr->data.eval.path;
		Tcl_IncrRefCount(cfPtr->data.eval.path);

		cfPtr->cmd.str.cmd = NULL;
		cfPtr->cmd.str.len = 0;



	    }

	    /*
	     * 'contextPtr' is going out of scope. Release the reference that
	     * it's holding to the source file path
	     */

	    Tcl_DecrRefCount(contextPtr->data.eval.path);
	}
	TclStackFree(interp, contextPtr);
    }
    Tcl_SetHashValue(Tcl_CreateHashEntry(iPtr->linePBodyPtr, procPtr,
	    &isNew), cfPtr);

    /*
     * Set the namespace for this lambda: given by objv[2] understood as a
     * global reference, or else global per default.
     */

    if (objc == 2) {

Changes to tests/proc.test.

370
371
372
373
374
375
376









377
378
379
380
381
382
383
	}
	return $i
    }
    ugly::foo
} -cleanup {
    namespace delete ugly
} -result 4










# cleanup
catch {rename p ""}
catch {rename t ""}
::tcltest::cleanupTests
return








>
>
>
>
>
>
>
>
>







370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
	}
	return $i
    }
    ugly::foo
} -cleanup {
    namespace delete ugly
} -result 4

test proc-7.4 {Proc struct outlives its interp: Bug 3532959} {
    set lambda x
    lappend lambda {set a 1}
    interp create slave
    slave eval [list apply $lambda foo]
    interp delete slave
    unset lambda
} {}

# cleanup
catch {rename p ""}
catch {rename t ""}
::tcltest::cleanupTests
return