summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2016-09-07 11:33:28 +0100
committerChris Liddell <chris.liddell@artifex.com>2016-09-13 16:23:26 +0100
commitcd95789bc8eaf0e86f902c8ba3f796340ffdad25 (patch)
treed7e7a8aecfceb66e7d57c63e3f0c752699aa9f34
parentdbfde5f3400e97b6d9b71a6549ff419dcefc9a95 (diff)
downloadghostpdl-cd95789bc8eaf0e86f902c8ba3f796340ffdad25.tar.gz
Ensure PCL/XPS free all their memory.
Noticed in passing (thrown up by ASAN): the plmain code was not fully shutting down the memory manager when using the chunk allocator. This commit adds a convenient function (gs_memory_chunk_wrap) and a pl_alloc_finit() function to ensure that all happens.
-rw-r--r--base/gsmalloc.c3
-rw-r--r--base/gsmchunk.c16
-rw-r--r--base/gsmchunk.h7
-rw-r--r--pcl/pl/plalloc.c7
-rw-r--r--pcl/pl/plalloc.h1
-rw-r--r--pcl/pl/plmain.c48
6 files changed, 65 insertions, 17 deletions
diff --git a/base/gsmalloc.c b/base/gsmalloc.c
index 9a8a09c1d..e8e17c640 100644
--- a/base/gsmalloc.c
+++ b/base/gsmalloc.c
@@ -337,7 +337,8 @@ gs_heap_free_object(gs_memory_t * mem, void *ptr, client_name_t cname)
bp->next->prev = bp->prev;
if (bp == mmem->allocated) {
mmem->allocated = bp->next;
- mmem->allocated->prev = NULL;
+ if (mmem->allocated)
+ mmem->allocated->prev = NULL;
}
mmem->used -= bp->size + sizeof(gs_malloc_block_t);
if (mmem->monitor)
diff --git a/base/gsmchunk.c b/base/gsmchunk.c
index 9bde4195e..b5a92eadc 100644
--- a/base/gsmchunk.c
+++ b/base/gsmchunk.c
@@ -175,6 +175,22 @@ gs_memory_chunk_release(gs_memory_t *mem)
"gs_memory_chunk_release");
}
+/* Release chunk memory manager, and return the target */
+gs_memory_t * /* Always succeeds */
+gs_memory_chunk_unwrap(gs_memory_t *mem)
+{
+ gs_memory_t *tmem;
+
+ if (mem->procs.status != chunk_status) {
+ tmem = mem;
+ }
+ else {
+ tmem = ((gs_memory_chunk_t *)mem)->target;
+ gs_memory_chunk_release(mem);
+ }
+ return tmem;
+}
+
/* ---------- Accessors ------------- */
/* Retrieve this allocator's target */
diff --git a/base/gsmchunk.h b/base/gsmchunk.h
index e46bae8ed..3464b2e9a 100644
--- a/base/gsmchunk.h
+++ b/base/gsmchunk.h
@@ -31,6 +31,13 @@ int gs_memory_chunk_wrap(gs_memory_t **wrapped, /* chunk allocator init */
/* Release a chunk memory manager and all of the memory it held */
void gs_memory_chunk_release(gs_memory_t *cmem);
+/* Release chunk memory manager, and return the target */
+/* if "mem" is not a chunk memory manager instance, "mem"
+ * is return untouched
+ */
+gs_memory_t * /* Always succeeds */
+gs_memory_chunk_unwrap(gs_memory_t *mem);
+
/* ---------- Accessors ------------- */
/* Retrieve this allocator's target */
diff --git a/pcl/pl/plalloc.c b/pcl/pl/plalloc.c
index d5441fc1b..78ba094a0 100644
--- a/pcl/pl/plalloc.c
+++ b/pcl/pl/plalloc.c
@@ -42,3 +42,10 @@ pl_alloc_init()
return pl_mem;
}
+
+void
+pl_alloc_finit(gs_memory_t *mem)
+{
+ gs_memory_t *tmem = gs_memory_chunk_unwrap(mem);
+ gs_malloc_release(tmem);
+}
diff --git a/pcl/pl/plalloc.h b/pcl/pl/plalloc.h
index d919f8be8..0e540bf2b 100644
--- a/pcl/pl/plalloc.h
+++ b/pcl/pl/plalloc.h
@@ -16,3 +16,4 @@
/* initialize the gs allocator. */
gs_memory_t *pl_alloc_init(void);
+void pl_alloc_finit(gs_memory_t *mem);
diff --git a/pcl/pl/plmain.c b/pcl/pl/plmain.c
index b58154191..499eda45c 100644
--- a/pcl/pl/plmain.c
+++ b/pcl/pl/plmain.c
@@ -257,6 +257,7 @@ pl_main_aux(int argc, char *argv[], void *disp)
pl_interp_instance_t *curr_instance = 0;
gs_c_param_list params;
int (*arg_get_codepoint) (FILE * file, const char **astr) = NULL;
+ int code = 0;
mem = pl_alloc_init();
@@ -303,7 +304,8 @@ pl_main_aux(int argc, char *argv[], void *disp)
pjl_instance, &inst, &pl_pre_finish_page,
&pl_post_finish_page) < 0) {
errprintf(mem, "%s", err_buf);
- return -1;
+ code = -1;
+ goto done;
}
#ifdef DEBUG
if (gs_debug_c(':'))
@@ -327,7 +329,8 @@ pl_main_aux(int argc, char *argv[], void *disp)
if (pl_init_job(pjl_instance) < 0) {
errprintf(mem, "Unable to init PJL job.\n");
- return -1;
+ code = -1;
+ goto done;
}
/* Process any new options. May request new device. */
@@ -360,7 +363,8 @@ pl_main_aux(int argc, char *argv[], void *disp)
}
errprintf(mem, "\n");
- return -1;
+ code = -1;
+ goto done;
}
if (!filename)
@@ -384,7 +388,8 @@ pl_main_aux(int argc, char *argv[], void *disp)
characteristics structure */
if (pl_main_cursor_open(mem, &r, filename, buf, sizeof(buf)) < 0) {
errprintf(mem, "Unable to open %s for reading.\n", filename);
- return -1;
+ code = -1;
+ goto done;
}
#ifdef DEBUG
@@ -407,7 +412,8 @@ pl_main_aux(int argc, char *argv[], void *disp)
pl_process_eof(curr_instance);
if (close_job(&universe, &inst) < 0) {
dmprintf(mem, "Unable to deinit PDL job.\n");
- return -1;
+ code = -1;
+ goto done;
}
}
break;
@@ -424,7 +430,8 @@ pl_main_aux(int argc, char *argv[], void *disp)
if (new_job) {
if (mem->gs_lib_ctx->gs_next_id > 0xFF000000) {
dmprintf(mem, "Once a year reset the gs_next_id.\n");
- return -1;
+ code = -1;
+ goto done;
}
if_debug0m('I', mem, "Selecting PDL\n");
@@ -437,12 +444,14 @@ pl_main_aux(int argc, char *argv[], void *disp)
params);
if (curr_instance == NULL) {
errprintf(mem, "%s", err_buf);
- return -1;
+ code = -1;
+ goto done;
}
if (pl_init_job(curr_instance) < 0) {
dmprintf(mem, "Unable to init PDL job.\n");
- return -1;
+ code = -1;
+ goto done;
}
if_debug1m('I', mem, "selected and initializing (%s)\n",
pl_characteristics(curr_instance->interp->
@@ -484,11 +493,13 @@ pl_main_aux(int argc, char *argv[], void *disp)
implementation)->language);
if (close_job(&universe, &inst) < 0) {
dmprintf(mem, "Unable to deinit PDL job.\n");
- return -1;
+ code = -1;
+ goto done;
}
if (pl_init_job(pjl_instance) < 0) {
dmprintf(mem, "Unable to init PJL job.\n");
- return -1;
+ code = -1;
+ goto done;
}
pl_renew_cursor_status(&r);
} else if (code < 0) { /* error and not exit language */
@@ -517,7 +528,8 @@ pl_main_aux(int argc, char *argv[], void *disp)
inst.error_report > 0);
if (close_job(&universe, &inst) < 0) {
dmprintf(mem, "Unable to deinit PJL.\n");
- return -1;
+ code = -1;
+ goto done;
}
/* Print PDL status if applicable, then dnit PDL job */
code = 0;
@@ -538,7 +550,8 @@ pl_main_aux(int argc, char *argv[], void *disp)
if (gx_saved_pages_param_process((gx_device_printer *)pdev,
(byte *)"print normal flush", 18) < 0) {
errprintf(mem, "Unable to print saved-pages.\n");
- return -1;
+ code = -1;
+ goto done;
}
}
/* release param list */
@@ -546,13 +559,15 @@ pl_main_aux(int argc, char *argv[], void *disp)
/* Dnit PDLs */
if (pl_main_universe_dnit(&universe, err_buf)) {
errprintf(mem, "%s", err_buf);
- return -1;
+ code = -1;
+ goto done;
}
/* dnit pjl */
if (pl_deallocate_interp_instance(pjl_instance) < 0
|| pl_deallocate_interp(pjl_interp) < 0) {
dmprintf(mem, "Unable to close out PJL instance.\n");
- return -1;
+ code = -1;
+ goto done;
}
/* We lost the ability to print peak memory usage with the loss
@@ -563,8 +578,9 @@ pl_main_aux(int argc, char *argv[], void *disp)
if (gs_debug_c('A'))
dmprintf(mem, "Final time");
pl_platform_dnit(0);
- gs_malloc_release(mem);
- return 0;
+ pl_alloc_finit(mem);
+done:
+ return code;
}
GSDLLEXPORT int GSDLLAPI