Tcl Source Code

View Ticket
Login
Ticket UUID: 154f0982f2f701a1c3f964c0a3d54737361a3630
Title: Tcl_NewObjectInstance() silently ignores existing namespace argument
Type: Bug Version: trunk
Submitter: dgp Created on: 2015-05-27 12:52:32
Subsystem: 35. TclOO Package Assigned To: dgp
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2024-09-09 08:57:01
Resolution: Fixed Closed By: oehhar
    Closed on: 2024-09-09 08:57:01
Description:
    Tcl_Object 
    Tcl_NewObjectInstance(interp, class, name, nsName, objc, objv, skip) 

...

const char *nsName (in)
    The name of the namespace to create for the object's private use, or NULL if a new unused name is to be automatically selected. 

...

If the nsName value passed in names an existing namespace, T_NOI() does
not raise an error, nor does it use the named namespace.  It silently
falls back to behaving as if nsName==NULL was passed in, and generates
a new namespace.

This should at least be made more clear in the documentation.

Itcl 4 suffers from this.  See http://core.tcl.tk/itcl/tktview?name=f3a2e7407c
User Comments: oehhar added on 2024-09-09 08:57:01:

The workaround is here: https://core.tcl-lang.org/itcl/info/46272cca4dc657b3

The TTT sees this as solved. Reverting on 8.6 would also be possible but this patch is also ok.

Thanks for all, Harald


dgp added on 2024-09-04 20:06:55:
While I am not able to solve these issues quickly, I was able
to hack in a workaround in Itcl.  Review and comment would
be helpful.

dgp added on 2024-09-04 18:52:41:
I do not possess a strong knowledge of what other codebases
make use of the TclOO C API and might also be upset by this.
How can we find out?

dgp added on 2024-09-04 18:47:46:
"it's technically a public API change, but one that I think nobody will notice and care about."

I don't see how that can be said when Itcl's expectations were what
raised the question in the first place, and testing Itcl immediately
shows the breakage.

The issues here are difficult and beyond what I can solve quickly.
But shouldn't we at least keep this breaking change out of 8.6.15?
As is, the release candidate of Tcl 8.6.15 breaks the released Itcl 4.2.5
as well as the latest sources poised to become Itcl 4.2.6.

dgp added on 2024-09-04 18:46:33:
To be more concrete, here are two of the simple test failures
in the Itcl test suite:

==== fossil-9.0 d0126511d9 FAILED
==== Contents of test case:

    itcl::class N {}

---- Test generated error; Return code was: 1
---- Return code should have been one of: 0 2
---- errorInfo: can't create namespace "N": already existsITCL: cannot create Tcl_NewObjectInstance for class "::N"
    while executing
"itcl::class N {}"
    ("uplevel" body line 2)
    invoked from within
"uplevel 1 $script"
---- errorCode: TCL OPERATION NAMESPACE CREATEEXISTING
---- Test cleanup failed:
class "N" not found in context "::"
---- errorInfo(cleanup): class "N" not found in context "::"
    while executing
"itcl::delete class N::B N"
    ("uplevel" body line 2)
    invoked from within
"uplevel 1 $cleanup"
---- errorCode(cleanup): NONE
==== fossil-9.0 FAILED



==== fossil-9.1 d0126511d9 FAILED
==== Contents of test case:

    itcl::class N {}

---- Test setup failed:
class "N::B" already exists
---- errorInfo(setup): class "N::B" already exists
    while executing
"itcl::class N::B {}"
    ("uplevel" body line 2)
    invoked from within
"uplevel 1 $setup"
---- errorCode(setup): NONE
---- Test cleanup failed:
class "N" not found in context "::"
---- errorInfo(cleanup): class "N" not found in context "::"
    while executing
"itcl::delete class N"
    ("uplevel" body line 2)
    invoked from within
"uplevel 1 $cleanup"
---- errorCode(cleanup): NONE
==== fossil-9.1 FAILED

These tests were created when the issue in this ticket was
first addressed back in 2015 to detect if it would ever come back.
Should not really be a surprise this change makes them fail.

dgp added on 2024-09-03 21:10:06:
I am sorry that my assessment is not timely, but this change
broke the trunk of Itcl. It creates multiple test suite
failures.

Since this change was put into both the 8.6 and 9.0 branches,
the issue is blocking releases until it is decided which must
change and how.

None of our auto-testing systems cover Itcl?  Can that be right?

dkf added on 2024-08-06 11:16:14:

Merged.


oehhar added on 2024-05-23 13:46:34:

Donal, thank you for the great fix.

The decision to merge or not should be done.

Please post your opinion here.

I will merge in one week (31th of May) if no strong objections. I will also write a message on the core list.

Thank you and take care, Harald


dkf added on 2024-05-23 13:27:27:

I don't like the panic option at all. The error option is in the bug-154f0982f2; it's technically a public API change, but one that I think nobody will notice and care about. A review of the C documentation made me think no alteration was required there.

If you want this change, merge the branch and close the issue.


dkf added on 2024-05-23 12:47:48:

There are two ways we could vary things from how they are now:

  1. Make AllocObject() return NULL in this case and not reset the result (so the underlying error in Tcl_CreateNamespace() can shine through, or we can generate our own error; we've definitely got a valid interp at that point. TclNewObjectInstanceCommon() can then pass the failure out (that function already has failure semantics in place so we don't need to check its callers).
  2. Make AllocObject() call Tcl_Panic() if it can't allocate the named namespace. I'm not keen on this option as I suspect it would make the panic definitely reachable from Tcl scripts.

There are other users of AllocObject() but they all pass NULL for nsNamePtr; they won't go down this code path. This is a total audit of callers of AllocObject() as that was, is, and always will be internal to tclOO.c; the other callers are in the function that sets up the base of the object hierarchy.


dkf added on 2024-05-23 11:38:58:

To reiterate, TclOO must create the namespace; it's going to attach its primary object metadata to the namespace (via the NS's clientData) and the only time it is safe to do that is at creation. An existing namespace probably ought to be an error, at least when using the Tcl script level API. C API users can be more careful.


dkf added on 2015-10-19 14:09:13:

Documented that the namespace should not already exist.


dgp added on 2015-10-08 12:58:52:
My (mild) preference is to leave this unresolved until I
can get back to and complete my experiments in Itcl 4 dealing
with the implications of this interface restriction.

dkf is welcome to comment on any necessities behind it.

jan.nijtmans added on 2015-10-07 13:48:04:
ping ... status?

mistachkin added on 2015-05-28 01:35:27:
It appears that the TclNRNewObjectInstance function duplicates some (or all?)
of the code involved as well.