Skip to content

Commit

Permalink
Fix memory management in Rugged (the lib is now GC-aware)
Browse files Browse the repository at this point in the history
Technically, a few memory leaks have been fixed. In practice, Rugged
wasn't freeing a single byte of memory from libgit2: now it is fully
GC-aware.

Signed-off-by: Vicent Marti <tanoku@gmail.com>
  • Loading branch information
vmg committed Dec 5, 2010
1 parent 1692669 commit e71a3f8
Show file tree
Hide file tree
Showing 11 changed files with 390 additions and 241 deletions.
45 changes: 40 additions & 5 deletions ext/rugged/rugged.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,50 @@ VALUE rb_git_object_init(git_otype type, int argc, VALUE *argv, VALUE self);

VALUE rugged_raw_read(git_repository *repo, const git_oid *oid);

VALUE rugged_person_c2rb(git_person *person);
VALUE rugged_object_c2rb(git_object *object);
VALUE rugged_person_new(git_person *person);
VALUE rugged_object_new(VALUE repository, git_object *object);
VALUE rugged_index_new(VALUE owner, git_index *index);

void rugged_person_rb2c(VALUE rb_person, const char **name_out, const char **email_out, unsigned long *time_out);
git_object *rugged_object_rb2c(git_repository *repo, VALUE object_value, git_otype type);
void rugged_person_get(VALUE rb_person, const char **name_out, const char **email_out, unsigned long *time_out);
git_object *rugged_object_get(git_repository *repo, VALUE object_value, git_otype type);

typedef struct rugged_backend {
typedef struct {
git_odb_backend parent;
VALUE self;
} rugged_backend;

typedef struct {
git_object *object;
VALUE owner;
} rugged_object;

typedef struct {
git_repository *repo;
VALUE backends;
} rugged_repository;

typedef struct {
git_index *index;
VALUE owner;
} rugged_index;

typedef struct {
git_revwalk *walk;
VALUE owner;
} rugged_walker;


#define RUGGED_OBJ_UNWRAP(_rb, _type, _c) {\
rugged_object *_rugged_obj; \
Data_Get_Struct(_rb, rugged_object, _rugged_obj); \
_c = (_type *)(_rugged_obj->object); \
}

#define RUGGED_OBJ_OWNER(_rb, _val) {\
rugged_object *_rugged_obj;\
Data_Get_Struct(_rb, rugged_object, _rugged_obj);\
_val = (_rugged_obj->owner);\
}


#endif
8 changes: 2 additions & 6 deletions ext/rugged/rugged_backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ int rugged_backend__generic_read(int header_only, git_rawobj *obj, git_odb_backe

obj->data = malloc(obj->len);
if (obj->data == NULL)
rb_raise(rb_eRuntimeError, "out of memory");
rb_raise(rb_eNoMemError, "out of memory");

memcpy(obj->data, RSTRING_PTR(rb_data), obj->len);
}
Expand All @@ -150,10 +150,6 @@ void rugged_backend__free(git_odb_backend *backend)

void rugged_backend__gcfree(void *data)
{
/*
* TODO: make sure that the ODB which owns us
* marks us as alive!!!!!!
*/
free(data);
}

Expand All @@ -176,7 +172,7 @@ static VALUE rb_git_backend_allocate(VALUE klass)

backend = calloc(1, sizeof(rugged_backend));
if (backend == NULL)
rb_raise(rb_eRuntimeError, "out of memory");
rb_raise(rb_eNoMemError, "out of memory");

backend->parent.read = &rugged_backend__read;
backend->parent.read_header = &rugged_backend__read_header;
Expand Down
13 changes: 3 additions & 10 deletions ext/rugged/rugged_blob.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@ extern VALUE rb_mRugged;
extern VALUE rb_cRuggedObject;
VALUE rb_cRuggedBlob;

static VALUE rb_git_blob_allocate(VALUE klass)
{
git_blob *blob = NULL;
return Data_Wrap_Struct(klass, NULL, NULL, blob);
}

static VALUE rb_git_blob_init(int argc, VALUE *argv, VALUE self)
{
return rb_git_object_init(GIT_OBJ_BLOB, argc, argv, self);
Expand All @@ -43,7 +37,7 @@ static VALUE rb_git_blob_init(int argc, VALUE *argv, VALUE self)
static VALUE rb_git_blob_content_SET(VALUE self, VALUE rb_contents)
{
git_blob *blob;
Data_Get_Struct(self, git_blob, blob);
RUGGED_OBJ_UNWRAP(self, git_blob, blob);

Check_Type(rb_contents, T_STRING);
git_blob_set_rawcontent(blob, RSTRING_PTR(rb_contents), RSTRING_LEN(rb_contents));
Expand All @@ -56,7 +50,7 @@ static VALUE rb_git_blob_content_GET(VALUE self)
git_blob *blob;
int size;

Data_Get_Struct(self, git_blob, blob);
RUGGED_OBJ_UNWRAP(self, git_blob, blob);

size = git_blob_rawsize(blob);
if (size == 0)
Expand All @@ -68,15 +62,14 @@ static VALUE rb_git_blob_content_GET(VALUE self)
static VALUE rb_git_blob_rawsize(VALUE self)
{
git_blob *blob;
Data_Get_Struct(self, git_blob, blob);
RUGGED_OBJ_UNWRAP(self, git_blob, blob);

return INT2FIX(git_blob_rawsize(blob));
}

void Init_rugged_blob()
{
rb_cRuggedBlob = rb_define_class_under(rb_mRugged, "Blob", rb_cRuggedObject);
rb_define_alloc_func(rb_cRuggedBlob, rb_git_blob_allocate);
rb_define_method(rb_cRuggedBlob, "initialize", rb_git_blob_init, -1);

rb_define_method(rb_cRuggedBlob, "size", rb_git_blob_rawsize, 0);
Expand Down
54 changes: 26 additions & 28 deletions ext/rugged/rugged_commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ extern VALUE rb_cRuggedObject;
extern VALUE rb_cRuggedPerson;
VALUE rb_cRuggedCommit;

VALUE rugged_person_c2rb(git_person *person)
VALUE rugged_person_new(git_person *person)
{
VALUE arguments[3];

Expand All @@ -44,7 +44,7 @@ VALUE rugged_person_c2rb(git_person *person)
return rb_class_new_instance(3, arguments, rb_cRuggedPerson);
}

void rugged_person_rb2c(VALUE rb_person, const char **name_out, const char **email_out, unsigned long *time_out)
void rugged_person_get(VALUE rb_person, const char **name_out, const char **email_out, unsigned long *time_out)
{
VALUE rb_name, rb_email, rb_time;

Expand All @@ -63,12 +63,6 @@ void rugged_person_rb2c(VALUE rb_person, const char **name_out, const char **ema
*time_out = rb_num2ulong(rb_time);
}

static VALUE rb_git_commit_allocate(VALUE klass)
{
git_commit *commit = NULL;
return Data_Wrap_Struct(klass, NULL, NULL, commit);
}

static VALUE rb_git_commit_init(int argc, VALUE *argv, VALUE self)
{
return rb_git_object_init(GIT_OBJ_COMMIT, argc, argv, self);
Expand All @@ -77,15 +71,15 @@ static VALUE rb_git_commit_init(int argc, VALUE *argv, VALUE self)
static VALUE rb_git_commit_message_GET(VALUE self)
{
git_commit *commit;
Data_Get_Struct(self, git_commit, commit);
RUGGED_OBJ_UNWRAP(self, git_commit, commit);

return rb_str_new2(git_commit_message(commit));
}

static VALUE rb_git_commit_message_SET(VALUE self, VALUE val)
{
git_commit *commit;
Data_Get_Struct(self, git_commit, commit);
RUGGED_OBJ_UNWRAP(self, git_commit, commit);

Check_Type(val, T_STRING);
git_commit_set_message(commit, RSTRING_PTR(val));
Expand All @@ -95,47 +89,47 @@ static VALUE rb_git_commit_message_SET(VALUE self, VALUE val)
static VALUE rb_git_commit_message_short_GET(VALUE self)
{
git_commit *commit;
Data_Get_Struct(self, git_commit, commit);
RUGGED_OBJ_UNWRAP(self, git_commit, commit);

return rb_str_new2(git_commit_message_short(commit));
}

static VALUE rb_git_commit_committer_GET(VALUE self)
{
git_commit *commit;
Data_Get_Struct(self, git_commit, commit);
RUGGED_OBJ_UNWRAP(self, git_commit, commit);

return rugged_person_c2rb((git_person *)git_commit_committer(commit));
return rugged_person_new((git_person *)git_commit_committer(commit));
}

static VALUE rb_git_commit_committer_SET(VALUE self, VALUE rb_person)
{
const char *name, *email;
time_t time;
git_commit *commit;
Data_Get_Struct(self, git_commit, commit);
RUGGED_OBJ_UNWRAP(self, git_commit, commit);

rugged_person_rb2c(rb_person, &name, &email, &time);
rugged_person_get(rb_person, &name, &email, &time);
git_commit_set_committer(commit, name, email, time);
return Qnil;
}

static VALUE rb_git_commit_author_GET(VALUE self)
{
git_commit *commit;
Data_Get_Struct(self, git_commit, commit);
RUGGED_OBJ_UNWRAP(self, git_commit, commit);

return rugged_person_c2rb((git_person *)git_commit_author(commit));
return rugged_person_new((git_person *)git_commit_author(commit));
}

static VALUE rb_git_commit_author_SET(VALUE self, VALUE rb_person)
{
const char *name, *email;
time_t time;
git_commit *commit;
Data_Get_Struct(self, git_commit, commit);
RUGGED_OBJ_UNWRAP(self, git_commit, commit);

rugged_person_rb2c(rb_person, &name, &email, &time);
rugged_person_get(rb_person, &name, &email, &time);
git_commit_set_author(commit, name, email, time);
return Qnil;
}
Expand All @@ -144,7 +138,7 @@ static VALUE rb_git_commit_author_SET(VALUE self, VALUE rb_person)
static VALUE rb_git_commit_time_GET(VALUE self)
{
git_commit *commit;
Data_Get_Struct(self, git_commit, commit);
RUGGED_OBJ_UNWRAP(self, git_commit, commit);

return ULONG2NUM(git_commit_time(commit));
}
Expand All @@ -153,19 +147,22 @@ static VALUE rb_git_commit_tree_GET(VALUE self)
{
git_commit *commit;
const git_tree *tree;
Data_Get_Struct(self, git_commit, commit);
VALUE owner;

RUGGED_OBJ_UNWRAP(self, git_commit, commit);
RUGGED_OBJ_OWNER(self, owner);

tree = git_commit_tree(commit);
return tree ? rugged_object_c2rb((git_object *)tree) : Qnil;
return tree ? rugged_object_new(owner, (git_object *)tree) : Qnil;
}

static VALUE rb_git_commit_tree_SET(VALUE self, VALUE val)
{
git_commit *commit;
git_tree *tree;
Data_Get_Struct(self, git_commit, commit);
RUGGED_OBJ_UNWRAP(self, git_commit, commit);

tree = (git_tree *)rugged_object_rb2c(git_object_owner((git_object *)commit), val, GIT_OBJ_TREE);
tree = (git_tree *)rugged_object_get(git_object_owner((git_object *)commit), val, GIT_OBJ_TREE);
git_commit_set_tree(commit, tree);
return Qnil;
}
Expand All @@ -175,12 +172,14 @@ static VALUE rb_git_commit_parents_GET(VALUE self)
git_commit *commit;
git_commit *parent;
unsigned int n;
VALUE ret_arr;
Data_Get_Struct(self, git_commit, commit);
VALUE ret_arr, owner;

RUGGED_OBJ_UNWRAP(self, git_commit, commit);
RUGGED_OBJ_OWNER(self, owner);

ret_arr = rb_ary_new();
for (n = 0; (parent = git_commit_parent(commit, n)) != NULL; n++) {
rb_ary_store(ret_arr, n, rugged_object_c2rb((git_object *)parent));
rb_ary_store(ret_arr, n, rugged_object_new(owner, (git_object *)parent));
}

return ret_arr;
Expand All @@ -189,7 +188,6 @@ static VALUE rb_git_commit_parents_GET(VALUE self)
void Init_rugged_commit()
{
rb_cRuggedCommit = rb_define_class_under(rb_mRugged, "Commit", rb_cRuggedObject);
rb_define_alloc_func(rb_cRuggedCommit, rb_git_commit_allocate);
rb_define_method(rb_cRuggedCommit, "initialize", rb_git_commit_init, -1);

rb_define_method(rb_cRuggedCommit, "message", rb_git_commit_message_GET, 0);
Expand Down
Loading

0 comments on commit e71a3f8

Please sign in to comment.