diff -up yum-3.2.29/yum/rpmtrans.py.old yum-3.2.29/yum/rpmtrans.py
--- yum-3.2.29/yum/rpmtrans.py.old	2014-04-08 17:50:52.000000000 +0200
+++ yum-3.2.29/yum/rpmtrans.py	2014-04-08 17:56:46.540520182 +0200
@@ -272,21 +272,58 @@ class RPMTransaction:
           hdr['release'], hdr['arch'])
 
         return handle
-    
+
+    def _fn_rm_installroot(self, filename):
+        """ Remove the installroot from the filename. """
+        # to handle us being inside a chroot at this point
+        # we hand back the right path to those 'outside' of the chroot() calls
+        # but we're using the right path inside.
+        if self.base.conf.installroot == '/':
+            return filename
+
+        return filename.replace(os.path.normpath(self.base.conf.installroot),'')
+
+    def ts_done_open(self):
+        """ Open the transaction done file, must be started outside the
+            chroot. """
+
+        if self.test: return False
+
+        if hasattr(self, '_ts_done'):
+            return True
+
+        self.ts_done_fn = '%s/transaction-done.%s' % (self.base.conf.persistdir,
+                                                      self._ts_time)
+        ts_done_fn = self._fn_rm_installroot(self.ts_done_fn)
+
+        try:
+            self._ts_done = open(ts_done_fn, 'w')
+        except (IOError, OSError), e:
+            self.display.errorlog('could not open ts_done file: %s' % e)
+            self._ts_done = None
+            return False
+        self._fdSetCloseOnExec(self._ts_done.fileno())
+        return True
+
+    def ts_done_write(self, msg):
+        """ Write some data to the transaction done file. """
+        if self._ts_done is None:
+            return
+
+        try:
+            self._ts_done.write(msg)
+            self._ts_done.flush()
+        except (IOError, OSError), e:
+            #  Having incomplete transactions is probably worse than having
+            # nothing.
+            self.display.errorlog('could not write to ts_done file: %s' % e)
+            self._ts_done = None
+            misc.unlink_f(self.ts_done_fn)
+
     def ts_done(self, package, action):
         """writes out the portions of the transaction which have completed"""
         
-        if self.test: return
-    
-        if not hasattr(self, '_ts_done'):
-            self.ts_done_fn = '%s/transaction-done.%s' % (self.base.conf.persistdir, self._ts_time)
-            
-            try:
-                self._ts_done = open(self.ts_done_fn, 'w')
-            except (IOError, OSError), e:
-                self.display.errorlog('could not open ts_done file: %s' % e)
-                return
-            self._fdSetCloseOnExec(self._ts_done.fileno())
+        if not self.ts_done_open(): return
         
         # walk back through self._te_tuples
         # make sure the package and the action make some kind of sense
@@ -323,14 +360,7 @@ class RPMTransaction:
         # hope springs eternal that this isn't wrong
         msg = '%s %s:%s-%s-%s.%s\n' % (t,e,n,v,r,a)
 
-        try:
-            self._ts_done.write(msg)
-            self._ts_done.flush()
-        except (IOError, OSError), e:
-            #  Having incomplete transactions is probably worse than having
-            # nothing.
-            del self._ts_done
-            misc.unlink_f(self.ts_done_fn)
+        self.ts_done_write(msg)
         self._te_tuples.pop(0)
     
     def ts_all(self):
@@ -362,17 +392,15 @@ class RPMTransaction:
         self._ts_time = time.strftime('%Y-%m-%d.%H:%M.%S')
         tsfn = '%s/transaction-all.%s' % (self.base.conf.persistdir, self._ts_time)
         self.ts_all_fn = tsfn
-        # to handle us being inside a chroot at this point
-        # we hand back the right path to those 'outside' of the chroot() calls
-        # but we're using the right path inside.
-        if self.base.conf.installroot != '/':
-            tsfn = tsfn.replace(os.path.normpath(self.base.conf.installroot),'')
+        tsfn = self._fn_rm_installroot(tsfn)
+
         try:
             if not os.path.exists(os.path.dirname(tsfn)):
                 os.makedirs(os.path.dirname(tsfn)) # make the dir,
             fo = open(tsfn, 'w')
         except (IOError, OSError), e:
             self.display.errorlog('could not open ts_all file: %s' % e)
+            self._ts_done = None
             return
 
         try:
@@ -384,7 +412,9 @@ class RPMTransaction:
         except (IOError, OSError), e:
             #  Having incomplete transactions is probably worse than having
             # nothing.
+            self.display.errorlog('could not write to ts_all file: %s' % e)
             misc.unlink_f(tsfn)
+            self._ts_done = None
 
     def callback( self, what, bytes, total, h, user ):
         if what == rpm.RPMCALLBACK_TRANS_START:
@@ -426,6 +456,7 @@ class RPMTransaction:
             if self.test: return
             self.trans_running = True
             self.ts_all() # write out what transaction will do
+            self.ts_done_open()
 
     def _transProgress(self, bytes, total, h):
         pass
diff -up yum-3.2.29/yum/history.py.old yum-3.2.29/yum/history.py
--- yum-3.2.29/yum/history.py.old	2014-04-09 10:17:55.000000000 +0200
+++ yum-3.2.29/yum/history.py	2014-04-09 10:22:28.515285115 +0200
@@ -726,6 +726,13 @@ class YumHistory:
             except (sqlite.OperationalError, sqlite.DatabaseError):
                 self.conf.readable = False
                 return None
+            #  Note that this is required due to changing the history DB in the
+            # callback for removed txmbrs ... which happens inside the chroot,
+            # as against all our other access which is outside the chroot. So
+            # we need sqlite to not open the journal.
+            #  In theory this sucks, as history could be shared. In reality
+            # it's deep yum stuff and there should only be one yum.
+            executeSQL(self._conn.cursor(), "PRAGMA locking_mode = EXCLUSIVE")
 
         return self._conn.cursor()
     def _commit(self):
