Tcl Source Code

View Ticket
Login
Ticket UUID: 1162286
Title: Inconsistent Tcl_PkgRequire return values
Type: Bug Version: obsolete: 8.5a4
Submitter: hemanglavana Created on: 2005-03-13 03:59:28
Subsystem: 39. Package Manager Assigned To: dgp
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2006-03-31 23:07:07
Resolution: Fixed Closed By: dgp
    Closed on: 2005-11-08 18:42:46
Description:
Hi,

The documentation for "package" command recommends that
"package provide <pkg> <ver>" should be at the bottom
of the library. However, most users are not aware of
the problem that can occur if the "package provide" cmd
is at the top of the library. This is illustrated in
the following example:

hlavana-u5:138> cat foo.tcl 
# foo.tcl
package provide foo 0.9.1
proc foo args {puts "PRINT: foo"}
set a ;# syntax error: var a is not defined
hlavana-u5:139>
hlavana-u5:139> cat pkgIndex.tcl 
# pkgIndex.tcl
package ifneeded foo 0.9.1 [list source [file join $dir
foo.tcl]]
hlavana-u5:140>
hlavana-u5:140> cat run_foo.tcl 
# run_foo.tcl
catch {package require foo} out1
puts "First time=$out1"
catch {package require foo} out2
puts "Second time=$out2"
hlavana-u5:141>
hlavana-u5:141> tclsh run_foo.tcl 
First time=can't read "a": no such variable
Second time=0.9.1
hlavana-u5:142>

This example shows that a script might end up thinking
that the package foo has been loaded successfully even
though  there were errors in loading it.

Moreover, most users like to see the "package provide
.." command appear at the top of the library even after
I have explained this issue to them. Note that many of
the packages in tcllib module have the "package
provide" command at the top of the script.

To overcome these problems, I would like to request an
enhancement: whenever "package require ..." fails to
load correctly, it should internally invoke "package
forget <pkg>". 

This specific solution does have one side-effect
though: consider that package foo, version 0.9 has been
successfully loaded  and the script is trying to load
package foo, version 1.1. If foo1.1 is not found, then
blindly calling "package forget foo" will
unload(forget) foo0.9 as well which is not correct.

I hope this issue can be resolved in the tcl-core
instead of asking users to move "package provide"
command to the bottom of the library.

Hemang.
User Comments: dgp added on 2006-03-31 23:07:07:
Logged In: YES 
user_id=80530


revised the 8.4.13 code
further so not even a warning
message is produced for the
forgiven category of error.

ready to commit when CVS returns

dgp added on 2005-11-19 02:23:51:
Logged In: YES 
user_id=80530


forgive.patch plus a few more 
tests committed for Tcl 8.4.12

hemanglavana added on 2005-11-18 06:12:25:
Logged In: YES 
user_id=81875

For sake of backwards compatibility, my suggestion is to
support the following style:

  package ifneeded foo 1 {package provide foo 1.1}

even though it may not be the right behavior. As was
recently found out with tcllib modules, you never know how
many more packages are relying on this "mis-feature". It may
be seen (by many) as introducing a non-compatible change
where it was not really needed.

Hemang.

dgp added on 2005-11-17 00:56:01:

File Added - 156499: forgive.patch

dgp added on 2005-11-17 00:55:54:
Logged In: YES 
user_id=80530

Attached patch makes Tcl 8.4.12
more forgiving of the

package ifneeded foo 1 {package provide foo 1.1}

category of error, because reportedly
a very large number of deployed
packages need such forgiveness.  :P

Not committing the patch right now.
Just wanted it available in case it's
determined that the pending Tcl 8.4.12
release must have it.

nobody added on 2005-11-09 22:02:22:
Logged In: NO 

Hi,

You also need to delete the following lines (in case you
haven't already fixed it) from the package man page:

http://www.tcl.tk/man/tcl8.4/TclCmd/package.htm
---
When writing a package implementation, you should put the
following at the bottom of your library script so it is only
called once the package has been successfully set up:

package provide foobar 1.0
---

Hemang.

dgp added on 2005-11-09 01:42:46:
Logged In: YES 
user_id=80530

that was an intentional backport
of a set of related tests,
namespace-25.7,8 and pkg-2.25,26 .

hemanglavana added on 2005-11-09 01:38:55:
Logged In: YES 
user_id=81875

The 8.4 patch contains two tests for namespace cmd which I
suspect are not related to this bug. Rest of the changes
look fine to me -- I have verified it on solaris2.8 with
tcl8.4 version.

Hemang.

dgp added on 2005-11-09 01:29:18:
Logged In: YES 
user_id=80530

patches committed

dgp added on 2005-11-09 01:04:43:

File Added - 155471: 1162286-84.patch

dgp added on 2005-11-09 01:04:42:
Logged In: YES 
user_id=80530


here's the corresponding patch
for 8.4

dgp added on 2005-11-08 04:42:21:

File Deleted - 154924: 



File Added - 155358: 1162286.patch

dgp added on 2005-11-08 04:42:20:
Logged In: YES 
user_id=80530


ok, the original report was one
case of several where the
value returned by Tcl_PkgRequire
could be inconsistent with the
state of the package database.

Please review this patch against
HEAD for taking care of these
matters (with tests).

hemanglavana added on 2005-11-04 23:56:41:
Logged In: YES 
user_id=81875

Packages should never have circular dependencies. If these
can be easily detected, circular dependencies should be
always reported as error.

Here's another (modified) example where detection of
circular dependencies will improve/aid debugging:

% package ifneeded foo 1 {
  package require bar 1
  package provide foo 1
}
% package ifneeded bar 1 {
  package require foo 1
  package provide bar 1 
}
% package require foo
too many nested evaluations (infinite loop?)
%

dgp added on 2005-11-04 21:59:30:
Logged In: YES 
user_id=80530


Before applying that patch:

% package ifneeded foo 1 {
  package require bar 1
  package provide foo 1
}
% package ifneeded foo 2 {
  package provide foo 2
}
% package ifneeded bar 1 {
  package require foo 2
  package provide bar 1
}
% package require foo 1 
conflicting versions provided for package "foo": 2, then 1
% package provide foo
2

After the patch:
(... same setup ...)
% package require foo 1
conflicting versions provided for package "foo": 2, then 1
% package provide foo
%

In this situation, there could now be
a weird mixture of foo 1 and foo 2 now
loaded in the interp.  It makes a bit
more sense not to claim one version or
the other, so the patch helps a bit.

However, the error message seems
misleading.  Perhaps would be better
to explictly detect and report circular
dependencies?

comments?

hemanglavana added on 2005-11-04 04:30:05:
Logged In: YES 
user_id=81875

Excellent. Your patch works fine for me. Hope this can be
committed to 8.4 branch.

Thank you.
Hemang.

dgp added on 2005-11-04 03:48:17:

File Added - 154924: 1162286.patch

dgp added on 2005-11-04 03:48:16:

data_type - 110894

Logged In: YES 
user_id=80530


Give this patch a try.

As the comment in the
patch notes, this looks more
like a bug than a feature
request, because of the
inconsistent return values
of repeated calls to 
Tcl_PkgRequire.

hemanglavana added on 2005-09-17 10:54:06:
Logged In: YES 
user_id=81875

On further thought, tcl interpreter already knows the
explicit version number it is trying to load when evaluating
the body of [package ifneeded ..] cmd. So there should not
be any side-effects if tcl internally invokes "package
forget <name> <version>" right after a failed 'sourcing' of
[package ifneeded] body.

Attachments: