Hi pacman dev list,

I am the guy behind pyalpmm and I found a not so small bug in libalpm.

As I wrote some unit-tests for pyalpmm I needed to open and close a
libalpm-"session" multiple times without restarting the calling
application. Something like that:

1. alpm_initialize();
2. /** do some operation here **/
3. alpm_release();
4. alpm_initialize();
5. alpm_release();

But I couldn't do this, because the alpm_initialize() call in line 4
always threw an error (errno: PM_ERR_HANDLE_NOT_NULL), which translates
to: "library already initialized". This is obviously not true, because
the alpm_release() function was successfully called.


I checked the code and found out that this line threw the error:

ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));

What means that the handle is not correctly reseted to NULL, but the
_alpm_free_handle() function, which is called by alpm_release() has a
FREE(handle) inside. So here is my explanation why this happens:

The handle pointer is passed to _alpm_free_handle() as a value, so the
pointer value itself is copied. This works perfect for freeing the
contents of the handle struct, BUT setting this handle pointer to NULL
just sets the locally copied pointer to NULL, what means the original
handle variable remains un-touched. So every alpm_initialize() call
after the first one will throw this error, no matter if you called
alpm_release() or not.

So to get finally end, I fixed it and the patch is (against latest git)
attached to this email. Hopefully my explanation is enough to sketch the
problem. Solving it, is really easy, just change the _alpm_free_handle()
function to take a pointer of a pointer of pmhandle_t as an argument,
change the references to handle inside the function and slightly change
the _alpm_free_handle() call in alpm_release(). That's how it is done
with the attached patch...

Finally I also have a question: I saw many changes in the recent git
compared to the latest release. Is there an estimated release date?

Thanks and Greets
Markus


diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c
index 6ab6516..c41c6fb 100644
--- a/lib/libalpm/alpm.c
+++ b/lib/libalpm/alpm.c
@@ -70,7 +70,7 @@ int SYMEXPORT alpm_release(void)
 		return(-1);
 	}
 
-	_alpm_handle_free(handle);
+	_alpm_handle_free(&handle);
 
 	return(0);
 }
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index 5cbf363..2a96071 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -54,10 +54,11 @@ pmhandle_t *_alpm_handle_new()
 	return(handle);
 }
 
-void _alpm_handle_free(pmhandle_t *handle)
+void _alpm_handle_free(pmhandle_t **handle_ptr)
 {
 	ALPM_LOG_FUNC;
-
+  
+  pmhandle_t *handle = *handle_ptr;
 	if(handle == NULL) {
 		return;
 	}
@@ -85,7 +86,7 @@ void _alpm_handle_free(pmhandle_t *handle)
 	FREELIST(handle->noextract);
 	FREELIST(handle->ignorepkg);
 	FREELIST(handle->ignoregrp);
-	FREE(handle);
+	FREE(*handle_ptr);
 }
 
 alpm_cb_log SYMEXPORT alpm_option_get_logcb()
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index a87d0fb..8a3265d 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -66,7 +66,7 @@ typedef struct _pmhandle_t {
 extern pmhandle_t *handle;
 
 pmhandle_t *_alpm_handle_new();
-void _alpm_handle_free(pmhandle_t *handle);
+void _alpm_handle_free(pmhandle_t **handle_ptr);
 
 #endif /* _ALPM_HANDLE_H */
 


Reply via email to