On 06/23/2011 04:17 PM, James Antill wrote:
On Thu, 2011-06-23 at 09:03 +0300, Panu Matilainen wrote:
On 06/23/2011 01:42 AM, James Antill wrote:
   So the problem is that AGAIN, when we log stuff for installed rpms we
do it in _instCloseFile, which is outside the chroot ... but when we log
stuff for erase rpms we do it in _unInstStop, which is inside the
chroot.
   sqlite will open it's journal file, which is it has a working path for
from outside the chroot ... being inside the chroot breaks this, which
results in complete failure of everything.

   Proposed fix is to move out of the chroot, before we call the
history/sqlite APIs, and then move back out again ... basically what rpm
does. Seems to work.
---
   yum/rpmtrans.py |    6 ++++++
   1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py
index 400d729..e0b7058 100644
--- a/yum/rpmtrans.py
+++ b/yum/rpmtrans.py
@@ -551,9 +551,15 @@ class RPMTransaction:
           if txmbr is not None:
               self._scriptout(txmbr.po)

+            #  Note that we are now back outside the smegging chroot, which
                                              ^^^^^^^

Should be inside, right?

  Yeh, I was a bit confused about ... mainly thinking in terms. of "in
chroot('.') and in chroot('/var/lib/mock/...')".

+            # confuses the heck out of sqlite when it tries to open it's 
journal
+            # file. So let's have fun:
+            os.chroot(".")
               pid   = self.base.history.pkg2pid(txmbr.po)
               state = self.base.history.txmbr2state(txmbr)
               self.base.history.trans_data_pid_end(pid, state)
+            os.chroot(self.base.conf.installroot)
+
               self.ts_done(txmbr.po, txmbr.output_state)
           else:
               self._scriptout(name)

Lets just say I'm not at all comfortable with the idea of chroot
switcheroo behind rpms back in a callback.

  I'm more than happy to do something else, but I can't think of any
better things to do:

1. Change the sqlite code in some way so that we can run from inside and
outside the chroot ... seems much more complicated, and more fragile.

2. Change the sqlite code so we have "two" DBs, one for inside and one
for outside the chroot ... oh, god no, please make it stop :).

3. Change the sqlite code so we keep the journal open over all the
rpmtrans calls (but delete it afterwards). I'm not sure this is
possible, and even if it is I'm not sure sqlite will be happy with the
chroot's even then.

This might be possible and even easy: when an sqlite db is opened in exclusive mode (which would be a perfectly reasonable thing for yum to do here) it doesn't look for the journal on every single access. I don't remember for 100% sure whether the exclusive mode stops ALL access to the journal, or whether it would actually truly fix this case, but it's at least worth trying out because it's just one single "PRAGMA locking_mode = EXCLUSIVE" statement.


4. Sync. the callbacks (or where we call the history code) so the APIs
are called from the same place (preferably outside) ... AFAIK this isn't
possible.

Keeping all accesses outside is not possible without changing rpm and I can't just go and change it because various users make assumptions where the calls happen... but maybe it would be possible to only update the history db when inside the chroot.

Or maybe you could extend the transaction_all/transaction_done stuff to include whatever info the history db needs and only update the history db once the transaction has completed from that data. Simple file descriptors behave nicely across chroots, but not many things do and sqlite (and BDB for that matter) are no exceptions. What yum is already doing in the callbacks is far far beyond what they originally were really intended for: handing back file descriptors and showing pretty progress meters. Removing complexity from the callback (updating external databases is pretty damn complex business in this context) would only be a good thing.


...do you like any of the above better? Or have more options?

Sometimes it's just better to say no if there's no reasonable solution.

Perhaps that one chroot pair wouldn't kill us, but where there's one, more are likely to follow, making it the whole thing even more complex and fragile. And then some unforeseen circumstance (such as a API user unintentionally catching OSError from failed chroot or such in their callback) causing rpm to end up outside the chroot when it should be inside it .. or something. I just find the prospects rather scary.

        - Panu -
_______________________________________________
Yum-devel mailing list
[email protected]
http://lists.baseurl.org/mailman/listinfo/yum-devel

Reply via email to