Issue 1267540: _register is not safe (original) (raw)

Issue1267540

Created on 2005-08-23 23:29 by reowen, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (3)
msg26103 - (view) Author: Russell Owen (reowen) Date: 2005-08-23 23:29
The _register function is not safe. It uses the following code to generate a unique string to identify a python callable entity: f = CallWrapper(func, subst, self).__call__ name = repr(id(f)) It then adds the function name if func has a __name__ attribute, but bound methods don't have that, and it is bound methods that cause the problem because they don't have a constant id number unless somebody bothers to keep an explicit reference to the bound reference around (keeping a reference to the object itself isn't enough). For example: class foo: def meth1(self): pass def meth2(self): pass f = foo() print id(f) print id(f.meth1) print id(f.meth2) Odds are good that the last two printed numbers will be the same even though they are for two different bound methods. The id of f will persist and remain unique as long as the object exists, but the id of its bound methods will not. Even though one can call the bound methods as long as the object persists. I don't know how to best handle this. Possibilities include: - Use hash(func) instead of id(func). I don't know enough about the built in hash to know if that is safe. Certainly it is the right idea. One wants a function that has the same value if the callable entity is the same and a different value otherwise. - Generate a new hash function that is sure to work. "paolino" suggested the following hash function for bound methods (when I first asked about this problem on comp.lang.python): id(boundMethod.im_self)^id(boundMethod.im_func) this is probably the simplest solution if hash itself isn't safe, but it requires a some fiddling to figure out what kind of callable entity one has, and thus what hash equation is suitable. - Keep a reference to the callable entity, so its id number cannot be reused. That sounds hard to do safely; it would be all too easy to introduce a memory leak. It can probably be done fairly easily for the case cleanup=1, but there is code that uses cleanup=0 (including bind_all and bind_class). -- Russell
msg26104 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2005-08-24 05:34
Logged In: YES user_id=21627 Can you provide a test case that demonstrates the problem? I don't think there is anything wrong with that code. We don't take the id of func, we take the id of f, where f is CallWrapper(...).__call__. f gets then passed to tk.createcommand, which in turn puts f into PythonCmd_ClientData. So as long as the Tcl command lives, f (which is indeed a method) is referenced, which in turn means that no other method can have the same id. You are also wrong that the name is not added for bound methods. It looks at im_func, and then takes the name of the function in the bound method. >>> f.meth1.im_func.__name__ 'meth1'
msg26105 - (view) Author: Russell Owen (reowen) Date: 2005-08-24 19:30
Logged In: YES user_id=431773 You are right. I should have realized that cratecommand kept a reference to the function (else how could it call it?). I replicated _register so as to not use a Tkinter internal function, and at some point ended up taking the id of the wrong thing. Sorry for the false alarm.
History
Date User Action Args
2022-04-11 14:56:12 admin set github: 42298
2005-08-23 23:29:05 reowen create