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. |