[pacman-dev] Transaction failure handling

Andrew Fyfe andrew at neptune-one.net
Thu Aug 30 18:50:51 EDT 2007


Xavier wrote:
> On Fri, Aug 17, 2007 at 03:47:22PM +0200, Xavier wrote:
>> On Thu, Aug 09, 2007 at 12:06:06PM +0200, Xavier wrote:
>>> While looking at FS#7652, I found something new :
>>> this problem doesn't happen on -S operations, only on -U, because of the
>>> following code in sync.c , _alpm_sync_commit function :
>>>
>>> 1027 error:
>>> 1028   _alpm_trans_free(tr);
>>> 1029   tr = NULL;
>>> 1030   /* commiting failed, so this is still just a prepared transaction */
>>> 1031   trans->state = STATE_PREPARED;
>>> 1032   return(-1);
>>>
>>> So if an error happens in sync code, the state goes back to STATE_PREPARED.
>>> That looks even more hackish than my patch above, but if it's better, then the
>>> same should be done in _alpm_add_commit and _alpm_remove_commit.
>>> Otherwise, it should be removed and handled somewhere else, like with my
>>> patch.
>>> Which way should we take?
>> Since Dan apparently started merging my unregister branch, I removed the two
>> above lines, since I think it doesn't make sense, and it's not consistent 
>> with the add and remove transactions.
>>
>>
>> From c2370ccbd322951d5c11f70096a440782de8c269 Mon Sep 17 00:00:00 2001
>> From: Chantry Xavier <shiningxc at gmail.com>
>> Date: Fri, 17 Aug 2007 14:07:56 +0200
>> Subject: [PATCH] libalpm/sync.c : don't go back on STATE_PREPARED when committing fails.
>>
>> In my opinion, a commiting transaction that failed isn't equivalent
>> to a prepared transaction.
>> Some things could have been done in the meantime.
>>
>> Signed-off-by: Chantry Xavier <shiningxc at gmail.com>
>> ---
>>  lib/libalpm/sync.c |    2 --
>>  1 files changed, 0 insertions(+), 2 deletions(-)
>>
>> diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
>> index 005123d..6c98aa3 100644
>> --- a/lib/libalpm/sync.c
>> +++ b/lib/libalpm/sync.c
>> @@ -1027,8 +1027,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
>>  error:
>>  	_alpm_trans_free(tr);
>>  	tr = NULL;
>> -	/* commiting failed, so this is still just a prepared transaction */
>> -	trans->state = STATE_PREPARED;
>>  	return(-1);
>>  }
>>  
>> -- 
>> 1.5.2.5
>>
> 
> That causes another problem though...
> in _alpm_trans_release, we have :
> 
> 184         /* during a commit do not interrupt immediately, just after a target */
> 185         if(trans->state == STATE_COMMITING || trans->state == STATE_INTERRUPTED) {
> 186                 if(trans->state == STATE_COMMITING) {
> 187                         trans->state = STATE_INTERRUPTED;
> 188                 }
> 189                 pm_errno = PM_ERR_TRANS_COMMITING;
> 190                 return(-1);
> 191         }
> 
> So since the state now stays on STATE_COMMITING (without going back to STATE_PREPARED)
> when a transaction fails, this code is now run, and the function returns here,
> without removing the lock.
> 
> Now, I'm totally unable to fix this correctly, the thing is, I really don't understand
> the purpose of this part, what it's intended to do, in which cases, etc ...
> 
> It annoyed me that pacman didn't remove the lock on each error (for example,
> conflicting targets), so I had to hack this, but that most likely kills totally what
> the original author had in mind, making the code worse than it is.
> 
> I guess what I'm trying to say here is that I need someone to look at this,
> and fix it correctly.
> Maybe I could revert that previous change in sync.c, so that the state goes back to
> STATE_PREPARED on failure, and then do the same in add.c / remove.c , but I
> still don't like that idea..
> 

I think this is another +1 for a rewrite. It seems for every bug we fix 
another harder to fix one pops up to take its place.

Andrew




More information about the pacman-dev mailing list