From: Manuel S. P. <san...@di...> - 2004-05-27 17:36:09
|
Hi 2 everybody!! I've been squeezing my brains with a deadlock until I've finally found out why it happened. The code is a bit hard to understand, so I'll simplify it a bit. We 've got bundle A and B. Bundle B has got a class C, which he exports, and bundle A imports it. Suppose A is already started. Now we start bundle B. In its activator, it contacts bundle B via RMI and tells him to instantiate class C (by reflection). The problem is that while bundle B is starting, bundle A cannot instantiate classes exported by bundle B. Usually, this is not a problem, because the call just waits until bundle B finishes starting. But in this case, a deadlock occurs, because bundle B won't finish until bundle A instantiates that class, and A won't instantiate that class until bundle B finishes. I think it has to do with the fact that while a bundle is STARTING it is not RESOLVED nor INSTALLED, and therefore no classes can be exported. Am I right? I mean, is this "my fault" in the sense that the spec states that the platform should act in this way, or is it a bug? Thanks!! Manuel Santillan |
From: Rob W. <ro...@as...> - 2004-05-28 08:37:28
|
Manuel Excuse me if this has already been answered - I only get the list digests, which come out a little delayed. >We 've got bundle A and B. Bundle B has got a class C, which he exports, >and bundle A imports it. > > > That part should be fine, it's the way OSGi is intended to work >Suppose A is already started. Now we start bundle B. In its activator, >it contacts bundle B via RMI and tells him to instantiate class C (by >reflection). The problem is that while bundle B is starting, bundle A >cannot instantiate classes exported by bundle B. Usually, this is not a >problem, because the call just waits until bundle B finishes starting. >But in this case, a deadlock occurs, because bundle B won't finish until >bundle A instantiates that class, and A won't instantiate that class >until bundle B finishes. > > > First and foremost, this sounds like a logic/coding deadlock to me. It seems you have a mutual dependency in your startup logic: - Bundle B needs Bundle A to do something before it can finish starting - Bundle A needs to load classes from Bundle B before it can finish starting. If I've understood this correctly, the only way you can break this deadlock is: - remove one of the dependencies e.g. let Bundle B start without any dependency on Bundle A. Sort out what Bundle B needs later, such as by using Services and have Bundle B wait for the required services to become available. - move the offending Class C (and any other dependent classes) into a pure "library" bundle that has no activator or active code, but just purely acts as a class library exporting classes for other bundles to use. Both Bundle A and Bundle B can then import these classes -- Rob |
From: Manuel S. P. <san...@di...> - 2004-05-28 09:55:41
|
Hi! I answer you inside the mail. > First and foremost, this sounds like a logic/coding deadlock to me. It > seems you have a mutual dependency in your startup logic: > > - Bundle B needs Bundle A to do something before it can finish starting > - Bundle A needs to load classes from Bundle B before it can finish > starting. Not exactly. Bundle A is already started and works fine. Then I start bundle B, which tells bundle A to instantiate a class. This class is exported by bundle B and imported by bundle A. > > If I've understood this correctly, the only way you can break this > deadlock is: > > - remove one of the dependencies e.g. let Bundle B start without any > dependency on Bundle A. Sort out what Bundle B needs later, such as by > using Services and have Bundle B wait for the required services to > become available. I've already used a similar approach, by extracting all the problematic code from bundle B and putting it in a bundle event listener which executes itself when the bundle B is already started. The thing is that if bundle B is in INSTALLED, RESOLVED OR STARTED state, then there is no problem in bundle A accesing a class from bundle B. However, if bundle A tries to access a class exported when bundle B is STARTING, he won't be able to do it. Is this the correct way of acting? Or should bundle A be able to access bundle B classes at any time? I mean, I 've already found workarounds for this problem. But I do not know if this is a bug (and therefore should need a fix) or is it just the way the spec says it should work. :) Thanks!! Regards, Manuel Santillan |
From: Michel D'H. <mic...@tr...> - 2004-05-28 10:54:49
|
Manuel Santillan Palencia wrote: >The thing is that if bundle B is in INSTALLED, RESOLVED OR STARTED >state, then there is no problem in bundle A accesing a class from bundle >B. However, if bundle A tries to access a class exported when bundle B >is STARTING, he won't be able to do it. > Is it really because it is in Starting state, or because of what is done in the start method? I mean, if you "sleep" for 1 minute in the start method of B, and you access a class from A as you do when B is in another state (installed, resolved or started), do you still have the problem? And the other way round? If you do what is in the start method when the bundle is started, are you still blocked? >Is this the correct way of acting? Or should bundle A be able to access bundle B classes at any time? > > I don't have time to look into the source of Oscar, but from what I can imagine, the class loader of B is exporting its packages as soon as it is installed. So we are back to pure Java, not OSGi, and the state of the bundle shall have no influence. Regards Michel |
From: Richard S. H. <he...@un...> - 2004-06-01 08:09:14
|
Manuel Santillan Palencia wrote: >I've already used a similar approach, by extracting all the problematic >code from bundle B and putting it in a bundle event listener which >executes itself when the bundle B is already started. > >The thing is that if bundle B is in INSTALLED, RESOLVED OR STARTED >state, then there is no problem in bundle A accesing a class from bundle >B. However, if bundle A tries to access a class exported when bundle B >is STARTING, he won't be able to do it. Is this the correct way of >acting? Or should bundle A be able to access bundle B classes at any >time? > > I think that Michel is correct when he states that it has nothing to do with the STARTING state, however, it could very likely be an Oscar issue in some respects. Oscar has to do some sanity locking so that it can ensure that refreshes don't happen in the middle of other operations, for example. It is difficult to explain the approach, but Oscar uses two locks, where one is intended for simple operations and one is intended for adminstrative operations. An administrative operation can ensure complete mutex by getting both locks. So what do I guess is happening in your case? Well, I haven't used RMI in a long, long time, but if I remember correctly, it uses threads. Most likely, Oscar calls out to your code, which then calls back into Oscar on a different thread trying to access the other bundle, which creates some sort of cycle. My guess is you could recreate the problem without RMI, but by just creating a separate thread that tries to load the class. >I mean, I 've already found workarounds for this problem. But I do not >know if this is a bug (and therefore should need a fix) or is it just >the way the spec says it should work. :) > If you can create a small example that demonstrates the problem, I will look into whether/how it is possible to loosen the concurrency control, but this is a very tricky issue. Obviously, Oscar cannot necessarily deal with people grabbing its thread in callbacks and then sending in a new thread. -> richard |
From: Michel D'H. <mic...@tr...> - 2004-05-28 07:55:37
|
Manuel Santillan Palencia wrote: >We 've got bundle A and B. Bundle B has got a class C, which he exports, >and bundle A imports it. > >Suppose A is already started. > How does A import class C? Is it through a dynamic-import in the manifest? Otherwise, it means that either B is already INSTALLED, or package of class C is exported by another bundle. >Now we start bundle B. In its activator, it contacts bundle B > you mean "it contacts bundle A", I guess! >via RMI and tells him to instantiate class C (by >reflection). The problem is that while bundle B is starting, bundle A >cannot instantiate classes exported by bundle B. > Well, according to me, it could, as explained below. >Usually, this is not a >problem, because the call just waits until bundle B finishes starting. >But in this case, a deadlock occurs, because bundle B won't finish until >bundle A instantiates that class, and A won't instantiate that class >until bundle B finishes. > > >I think it has to do with the fact that while a bundle is STARTING it >is not RESOLVED nor INSTALLED, and therefore no classes can be exported. >Am I right? > > The sequence is INSTALLED, RESOLVED then STARTING. If you take as an example the case of a library bundle, just being INSTALLED is enough to export packages, so bundle A could access class C as soon as bundle B is installed. >I mean, is this "my fault" in the sense that the spec states that the >platform should act in this way, or is it a bug? > > I am just wondering why you are using RMI between bundles. Besides, I miss deeper knowledge on how class C is shared. Regards Michel |