Return {error, enonmem} in OOM situations

This commit is contained in:
Carlos Martín Nieto
2013-05-02 11:37:35 +02:00
parent 0aa11d8532
commit ef7d2d5490
11 changed files with 56 additions and 39 deletions

View File

@@ -39,7 +39,7 @@ geef_blob_content(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return atoms.error; return atoms.error;
if (!enif_alloc_binary(len, &bin)) if (!enif_alloc_binary(len, &bin))
return atoms.error; return geef_oom(env);
memcpy(bin.data, content, len); memcpy(bin.data, content, len);

View File

@@ -18,7 +18,7 @@ geef_commit_tree_id(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
id = git_commit_tree_id((git_commit *) obj->obj); id = git_commit_tree_id((git_commit *) obj->obj);
if (geef_oid_bin(&bin, id) < 0) if (geef_oid_bin(&bin, id) < 0)
return atoms.error; return geef_oom(env);
return enif_make_binary(env, &bin); return enif_make_binary(env, &bin);
} }

View File

@@ -73,6 +73,9 @@ static int load(ErlNifEnv *env, void **priv, ERL_NIF_TERM load_info)
atoms.timesort = enif_make_atom(env, "sort_time"); atoms.timesort = enif_make_atom(env, "sort_time");
atoms.reversesort = enif_make_atom(env, "sort_reverse"); atoms.reversesort = enif_make_atom(env, "sort_reverse");
atoms.iterover = enif_make_atom(env, "iterover"); atoms.iterover = enif_make_atom(env, "iterover");
/* Errors */
atoms.enomem = enif_make_atom(env, "enomem");
atoms.eunknown = enif_make_atom(env, "eunknown");
return 0; return 0;
} }
@@ -92,24 +95,34 @@ geef_error(ErlNifEnv *env)
{ {
const git_error *error; const git_error *error;
ErlNifBinary bin; ErlNifBinary bin;
const char *message;
size_t len; size_t len;
error = giterr_last(); error = giterr_last();
if (error && error->message)
message = error->message;
else
message = "No message specified";
len = strlen(message); if (!error)
return enif_make_tuple2(env, atoms.error, atoms.eunknown);
if (error->klass == GITERR_NOMEMORY)
return geef_oom(env);
if (!error->message)
return enif_make_tuple2(env, atoms.error, atoms.eunknown);
len = strlen(error->message);
if (!enif_alloc_binary(len, &bin)) if (!enif_alloc_binary(len, &bin))
return atoms.error; return geef_oom(env);
memcpy(bin.data, message, len); memcpy(bin.data, error->message, len);
return enif_make_tuple2(env, atoms.error, enif_make_binary(env, &bin)); return enif_make_tuple2(env, atoms.error, enif_make_binary(env, &bin));
} }
ERL_NIF_TERM
geef_oom(ErlNifEnv *env)
{
return enif_make_tuple2(env, atoms.error, atoms.enomem);
}
static ErlNifFunc geef_funcs[] = static ErlNifFunc geef_funcs[] =
{ {
{"repository_init", 2, geef_repository_init}, {"repository_init", 2, geef_repository_init},

View File

@@ -4,6 +4,7 @@
#include "erl_nif.h" #include "erl_nif.h"
ERL_NIF_TERM geef_error(ErlNifEnv *env); ERL_NIF_TERM geef_error(ErlNifEnv *env);
ERL_NIF_TERM geef_oom(ErlNifEnv *env);
typedef struct { typedef struct {
ERL_NIF_TERM ok; ERL_NIF_TERM ok;
@@ -21,6 +22,9 @@ typedef struct {
ERL_NIF_TERM timesort; ERL_NIF_TERM timesort;
ERL_NIF_TERM reversesort; ERL_NIF_TERM reversesort;
ERL_NIF_TERM iterover; ERL_NIF_TERM iterover;
ERL_NIF_TERM enomem;
ERL_NIF_TERM eunknown;
} geef_atoms; } geef_atoms;
extern geef_atoms atoms; extern geef_atoms atoms;

View File

@@ -19,7 +19,7 @@ geef_index_new(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
index = enif_alloc_resource(geef_index_type, sizeof(geef_index)); index = enif_alloc_resource(geef_index_type, sizeof(geef_index));
if (!index) if (!index)
return atoms.error; return geef_oom(env);
if (git_index_new(&index->index) < 0) if (git_index_new(&index->index) < 0)
return geef_error(env); return geef_error(env);
@@ -69,7 +69,7 @@ geef_index_write_tree(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return geef_error(env); return geef_error(env);
if (geef_oid_bin(&bin, &id) < 0) if (geef_oid_bin(&bin, &id) < 0)
return atoms.error; return geef_oom(env);
return enif_make_tuple2(env, atoms.ok, enif_make_binary(env, &bin)); return enif_make_tuple2(env, atoms.ok, enif_make_binary(env, &bin));
} }

View File

@@ -64,7 +64,7 @@ geef_object_lookup(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
obj = enif_alloc_resource(geef_object_type, sizeof(geef_object)); obj = enif_alloc_resource(geef_object_type, sizeof(geef_object));
if (!obj) if (!obj)
return atoms.error; return geef_oom(env);
if (git_object_lookup(&obj->obj, repo->repo, &id, GIT_OBJ_ANY) < 0) { if (git_object_lookup(&obj->obj, repo->repo, &id, GIT_OBJ_ANY) < 0) {
enif_release_resource(obj); enif_release_resource(obj);
@@ -94,7 +94,7 @@ geef_object_id(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
id = git_object_id(obj->obj); id = git_object_id(obj->obj);
if (geef_oid_bin(&bin, id) < 0) if (geef_oid_bin(&bin, id) < 0)
return atoms.error; return geef_oom(env);
return enif_make_tuple2(env, atoms.ok, enif_make_binary(env, &bin)); return enif_make_tuple2(env, atoms.ok, enif_make_binary(env, &bin));
} }

View File

@@ -26,7 +26,7 @@ geef_oid_fmt(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return enif_make_badarg(env); return enif_make_badarg(env);
if (!enif_alloc_binary(GIT_OID_HEXSZ, &bin_out)) if (!enif_alloc_binary(GIT_OID_HEXSZ, &bin_out))
return atoms.error; return geef_oom(env);
git_oid_fromraw(&id, bin.data); git_oid_fromraw(&id, bin.data);
git_oid_fmt((char *)bin_out.data, &id); git_oid_fmt((char *)bin_out.data, &id);
@@ -46,7 +46,7 @@ geef_oid_parse(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
git_oid_fromstrn(&id, (const char *)bin.data, bin.size); git_oid_fromstrn(&id, (const char *)bin.data, bin.size);
if (geef_oid_bin(&bin_out, &id) < 0) if (geef_oid_bin(&bin_out, &id) < 0)
return atoms.error; return geef_oom(env);
return enif_make_binary(env, &bin_out); return enif_make_binary(env, &bin_out);
} }

View File

@@ -38,7 +38,7 @@ geef_reference_list(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
on_error: on_error:
git_strarray_free(&array); git_strarray_free(&array);
return atoms.error; return geef_oom(env);
} }
ERL_NIF_TERM ERL_NIF_TERM
@@ -60,7 +60,7 @@ geef_reference_lookup(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
name = malloc(bin.size + 1); name = malloc(bin.size + 1);
if (!name) if (!name)
return atoms.error; return geef_oom(env);
memcpy(name, bin.data, bin.size); memcpy(name, bin.data, bin.size);
name[bin.size] = '\0'; name[bin.size] = '\0';
@@ -142,7 +142,7 @@ geef_reference_glob(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
glob = malloc(bin.size + 1); glob = malloc(bin.size + 1);
if (!glob) if (!glob)
return atoms.error; return geef_oom(env);
memcpy(glob, bin.data, bin.size); memcpy(glob, bin.data, bin.size);
glob[bin.size] = '\0'; glob[bin.size] = '\0';
@@ -173,7 +173,7 @@ geef_reference_target(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
id = git_reference_target(ref->ref); id = git_reference_target(ref->ref);
if (geef_oid_bin(&bin, id) < 0) if (geef_oid_bin(&bin, id) < 0)
return atoms.error; return geef_oom(env);
} else { } else {
const char *name; const char *name;
size_t len; size_t len;
@@ -182,7 +182,7 @@ geef_reference_target(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
len = strlen(name); len = strlen(name);
if (enif_alloc_binary(len, &bin) < 0) if (enif_alloc_binary(len, &bin) < 0)
return atoms.error; return geef_oom(env);
memcpy(bin.data, name, len + 1); memcpy(bin.data, name, len + 1);
} }
@@ -206,7 +206,7 @@ geef_reference_to_id(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
name = malloc(bin.size + 1); name = malloc(bin.size + 1);
if (!name) if (!name)
return atoms.error; return geef_oom(env);
memcpy(name, bin.data, bin.size); memcpy(name, bin.data, bin.size);
name[bin.size] = '\0'; name[bin.size] = '\0';
@@ -215,7 +215,7 @@ geef_reference_to_id(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return geef_error(env); return geef_error(env);
if (geef_oid_bin(&bin, &id) < 0) if (geef_oid_bin(&bin, &id) < 0)
return atoms.error; return geef_oom(env);
return enif_make_tuple2(env, atoms.ok, enif_make_binary(env, &bin)); return enif_make_tuple2(env, atoms.ok, enif_make_binary(env, &bin));
} }
@@ -268,7 +268,7 @@ geef_reference_create(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
/* Allocate the extra byte for the NUL terminator */ /* Allocate the extra byte for the NUL terminator */
if (!enif_realloc_binary(&name, name.size + 1)) if (!enif_realloc_binary(&name, name.size + 1))
return atoms.error; return geef_oom(env);
name.data[name.size-1] = '\0'; name.data[name.size-1] = '\0';
@@ -283,7 +283,7 @@ geef_reference_create(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
} else if (enif_is_identical(argv[2], atoms.symbolic)) { } else if (enif_is_identical(argv[2], atoms.symbolic)) {
/* Allocate the extra byte for the NUL terminator */ /* Allocate the extra byte for the NUL terminator */
if (!enif_realloc_binary(&target, target.size + 1)) if (!enif_realloc_binary(&target, target.size + 1))
return atoms.error; return geef_oom(env);
target.data[target.size - 1] = '\0'; target.data[target.size - 1] = '\0';
ptarget = (const char *) target.data; ptarget = (const char *) target.data;

View File

@@ -32,7 +32,7 @@ geef_repository_init(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
path = malloc(bin.size + 1); path = malloc(bin.size + 1);
if (!path) if (!path)
return atoms.error; return geef_oom(env);
memcpy(path, bin.data, bin.size); memcpy(path, bin.data, bin.size);
path[bin.size] = '\0'; path[bin.size] = '\0';
@@ -68,7 +68,7 @@ geef_repository_open(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
path = malloc(bin.size + 1); path = malloc(bin.size + 1);
if (!path) if (!path)
return atoms.error; return geef_oom(env);
memcpy(path, bin.data, bin.size); memcpy(path, bin.data, bin.size);
path[bin.size] = '\0'; path[bin.size] = '\0';
@@ -100,7 +100,7 @@ geef_repository_discover(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
path = malloc(bin.size + 1); path = malloc(bin.size + 1);
if (!path) if (!path)
return atoms.error; return geef_oom(env);
memcpy(path, bin.data, bin.size); memcpy(path, bin.data, bin.size);
path[bin.size] = '\0'; path[bin.size] = '\0';
@@ -108,7 +108,7 @@ geef_repository_discover(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
buffer_len = 256; buffer_len = 256;
buffer = malloc(buffer_len); buffer = malloc(buffer_len);
if (!buffer) if (!buffer)
return atoms.error; return geef_oom(env);
while ((error = git_repository_discover(buffer, buffer_len, path, 0, NULL)) < 0 && while ((error = git_repository_discover(buffer, buffer_len, path, 0, NULL)) < 0 &&
giterr_last()->klass == GITERR_REPOSITORY) { giterr_last()->klass == GITERR_REPOSITORY) {
@@ -118,7 +118,7 @@ geef_repository_discover(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
if (!tmp) { if (!tmp) {
free(path); free(path);
free(buffer); free(buffer);
return atoms.error; return geef_oom(env);
} }
buffer = tmp; buffer = tmp;
@@ -134,7 +134,7 @@ geef_repository_discover(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
buffer_len = strlen(buffer); buffer_len = strlen(buffer);
if (!enif_alloc_binary(buffer_len, &res_bin)) { if (!enif_alloc_binary(buffer_len, &res_bin)) {
free(buffer); free(buffer);
return atoms.error; return geef_oom(env);
} }
memcpy(res_bin.data, buffer, buffer_len); memcpy(res_bin.data, buffer, buffer_len);
@@ -158,7 +158,7 @@ geef_repository_path(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
len = strlen(path); len = strlen(path);
if (!enif_alloc_binary(len, &bin)) if (!enif_alloc_binary(len, &bin))
return atoms.error; return geef_oom(env);
memcpy(bin.data, path, len); memcpy(bin.data, path, len);
return enif_make_binary(env, &bin); return enif_make_binary(env, &bin);
@@ -182,7 +182,7 @@ geef_repository_workdir(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
len = strlen(path); len = strlen(path);
if (!enif_alloc_binary(len, &bin)) if (!enif_alloc_binary(len, &bin))
return atoms.error; return geef_oom(env);
memcpy(bin.data, path, len); memcpy(bin.data, path, len);
return enif_make_binary(env, &bin); return enif_make_binary(env, &bin);
@@ -266,7 +266,7 @@ geef_odb_write(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return geef_error(env); return geef_error(env);
if (geef_oid_bin(&oid_bin, &oid) < 0) if (geef_oid_bin(&oid_bin, &oid) < 0)
return atoms.error; return geef_oom(env);
return enif_make_tuple2(env, atoms.ok, enif_make_binary(env, &oid_bin)); return enif_make_tuple2(env, atoms.ok, enif_make_binary(env, &oid_bin));
} }

View File

@@ -23,7 +23,7 @@ geef_revwalk_new(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
walk = enif_alloc_resource(geef_revwalk_type, sizeof(geef_revwalk)); walk = enif_alloc_resource(geef_revwalk_type, sizeof(geef_revwalk));
if (!walk) if (!walk)
return atoms.error; return geef_oom(env);
if (git_revwalk_new(&walk->walk, repo->repo) < 0) { if (git_revwalk_new(&walk->walk, repo->repo) < 0) {
enif_release_resource(walk); enif_release_resource(walk);
@@ -70,7 +70,7 @@ geef_revwalk_next(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return enif_make_badarg(env); return enif_make_badarg(env);
if (!enif_alloc_binary(GIT_OID_RAWSZ, &bin)) if (!enif_alloc_binary(GIT_OID_RAWSZ, &bin))
return atoms.error; return geef_oom(env);
if ((error = git_revwalk_next((git_oid *)bin.data, walk->walk)) < 0) { if ((error = git_revwalk_next((git_oid *)bin.data, walk->walk)) < 0) {
if (error == GIT_ITEROVER) if (error == GIT_ITEROVER)

View File

@@ -24,11 +24,11 @@ static ERL_NIF_TERM tree_entry_to_term(ErlNifEnv *env, const git_tree_entry *ent
ErlNifBinary name, oid; ErlNifBinary name, oid;
if (geef_oid_bin(&oid, git_tree_entry_id(entry)) < 0) if (geef_oid_bin(&oid, git_tree_entry_id(entry)) < 0)
return atoms.error; return geef_oom(env);
if (geef_string_bin(&name, git_tree_entry_name(entry)) < 0) { if (geef_string_bin(&name, git_tree_entry_name(entry)) < 0) {
enif_release_binary(&name); enif_release_binary(&name);
return atoms.error; return geef_oom(env);
} }
return enif_make_tuple5(env, atoms.ok, enif_make_int(env, git_tree_entry_filemode(entry)), return enif_make_tuple5(env, atoms.ok, enif_make_int(env, git_tree_entry_filemode(entry)),
@@ -54,7 +54,7 @@ geef_tree_bypath(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
path = malloc(bin.size + 1); path = malloc(bin.size + 1);
if (!path) if (!path)
return atoms.error; return geef_oom(env);
memcpy(path, bin.data, bin.size); memcpy(path, bin.data, bin.size);
path[bin.size] = '\0'; path[bin.size] = '\0';