diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/memory.c | 11 | ||||
-rw-r--r-- | src/memory.h | 2 | ||||
-rw-r--r-- | src/parser.c | 6 | ||||
-rw-r--r-- | src/search.c | 18 | ||||
-rw-r--r-- | src/spawn.c | 5 |
5 files changed, 28 insertions, 14 deletions
diff --git a/src/memory.c b/src/memory.c index c80ccc7..302939b 100644 --- a/src/memory.c +++ b/src/memory.c @@ -658,10 +658,17 @@ teco_memory_set_limit(gsize new_limit, GError **error) return TRUE; } +/** + * Check whether the memory limit is exceeded or would be + * exceeded by an allocation. + * + * @param request Size of the requested allocation or 0 if + * you want to check the current memory usage. + */ gboolean -teco_memory_check(GError **error) +teco_memory_check(gsize request, GError **error) { - gsize memory_usage = g_atomic_int_get(&teco_memory_usage); + gsize memory_usage = g_atomic_int_get(&teco_memory_usage) + request; if (G_UNLIKELY(teco_memory_limit && memory_usage > teco_memory_limit)) { g_autofree gchar *limit_str = g_format_size(memory_usage); diff --git a/src/memory.h b/src/memory.h index 58705a7..b2160e7 100644 --- a/src/memory.h +++ b/src/memory.h @@ -25,4 +25,4 @@ void teco_memory_stop_limiting(void); gboolean teco_memory_set_limit(gsize new_limit, GError **error); -gboolean teco_memory_check(GError **error); +gboolean teco_memory_check(gsize request, GError **error); diff --git a/src/parser.c b/src/parser.c index ff1fd18..22f7a4f 100644 --- a/src/parser.c +++ b/src/parser.c @@ -105,7 +105,11 @@ teco_machine_main_step(teco_machine_main_t *ctx, const gchar *macro, gint stop_p goto error_attach; } - if (!teco_memory_check(error)) + /* + * Most allocations are small or of limited size, + * so it is (almost) sufficient to check the memory limit regularily. + */ + if (!teco_memory_check(0, error)) goto error_attach; if (!teco_machine_input(&ctx->parent, macro[ctx->macro_pc], error)) diff --git a/src/search.c b/src/search.c index e5e4bd8..4c324a6 100644 --- a/src/search.c +++ b/src/search.c @@ -28,6 +28,7 @@ #include "string-utils.h" #include "expressions.h" #include "interface.h" +#include "memory.h" #include "undo.h" #include "qreg.h" #include "ring.h" @@ -492,17 +493,18 @@ teco_do_search(GRegex *re, gint from, gint to, gint *count, GError **error) gint from, to; } teco_range_t; + gsize matched_size = sizeof(teco_range_t) * -*count; + /* - * NOTE: It's theoretically possible that this single allocation - * causes an OOM if (-count) is large enough and memory limiting won't help. - * That's why we exceptionally have to check for allocation success. + * NOTE: It's theoretically possible that the allocation of the `matched` + * array causes an OOM if (-count) is large enough and regular + * memory limiting in teco_machine_main_step() wouldn't help. + * That's why we exceptionally have to check before allocating. */ - g_autofree teco_range_t *matched = g_try_new(teco_range_t, -*count); - if (!matched) { - g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED, - "Search count too small (%d)", *count); + if (!teco_memory_check(matched_size, error)) return FALSE; - } + + g_autofree teco_range_t *matched = g_malloc(matched_size); gint matched_total = 0, i = 0; diff --git a/src/spawn.c b/src/spawn.c index 1406731..00ff3ad 100644 --- a/src/spawn.c +++ b/src/spawn.c @@ -640,10 +640,11 @@ teco_spawn_stdout_watch_cb(GIOChannel *chan, GIOCondition condition, gpointer da teco_spawn_ctx.text_added = TRUE; /* - * NOTE: Since this reads from an external process, we could insert + * NOTE: Since this reads from an external process and regular memory + * limiting in teco_machine_main_step() is not performed, we could insert * indefinitely (eg. cat /dev/zero). */ - if (!teco_memory_check(&teco_spawn_ctx.error)) + if (!teco_memory_check(0, &teco_spawn_ctx.error)) goto error; } |