[master] 97537cb17 Create a directory owned by the worker process for use as a TMPDIR

Nils Goroll nils.goroll at uplex.de
Mon May 27 15:46:02 UTC 2024


commit 97537cb1784f69a5862acf6d4e78713a2cb1e033
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Mon May 27 17:43:22 2024 +0200

    Create a directory owned by the worker process for use as a TMPDIR
    
    Processes created by the worker might require a TMPDIR for temporary
    files (think: filters). Create a dedicated directory for this purpose,
    which is otherwise hard to achieve in a universal manner.

diff --git a/bin/varnishd/mgt/mgt_main.c b/bin/varnishd/mgt/mgt_main.c
index 192ae202a..1b2ddbc2f 100644
--- a/bin/varnishd/mgt/mgt_main.c
+++ b/bin/varnishd/mgt/mgt_main.c
@@ -319,6 +319,7 @@ mgt_Cflag_atexit(void)
 		VJ_rmdir("vext_cache");
 	}
 	VJ_rmdir("vmod_cache");
+	VJ_rmdir("worker_tmpdir");
 	(void)chdir("/");
 	VJ_rmdir(workdir);
 }
@@ -865,7 +866,7 @@ main(int argc, char * const *argv)
 		    workdir, VAS_errtxt(errno));
 
 	VJ_master(JAIL_MASTER_SYSTEM);
-	AZ(system("rm -rf vmod_cache vext_cache"));
+	AZ(system("rm -rf vmod_cache vext_cache worker_tmpdir"));
 	VJ_master(JAIL_MASTER_LOW);
 
 	if (VJ_make_subdir("vmod_cache", "VMOD cache", NULL)) {
@@ -881,6 +882,13 @@ main(int argc, char * const *argv)
 		    workdir, VAS_errtxt(errno));
 	}
 
+	if (VJ_make_subdir("worker_tmpdir",
+	    "TMPDIR for the worker process", NULL)) {
+		ARGV_ERR(
+		    "Cannot create vmod directory (%s/worker_tmpdir): %s\n",
+		    workdir, VAS_errtxt(errno));
+	}
+
 	if (C_flag)
 		AZ(atexit(mgt_Cflag_atexit));
 
diff --git a/doc/changes.rst b/doc/changes.rst
index dbe31e3ab..ba74f7c13 100644
--- a/doc/changes.rst
+++ b/doc/changes.rst
@@ -41,11 +41,17 @@ Varnish Cache NEXT (2024-09-15)
 .. PLEASE keep this roughly in commit order as shown by git-log / tig
    (new to old)
 
+* ``varnishd`` now creates a ``worker_tmpdir`` which can be used by
+  VMODs for temporary files. The `VMOD deleveloper documentation`_ has
+  details.
+
 * The environment variable ``VARNISH_DEFAULT_N`` now provides the
   default "varnish name" / "workdir" as otherwise specified by he
   ``-n`` argument to ``varnishd`` and ``varnish*`` utilities except
   ``varnishtest``.
 
+.. _VMOD deleveloper documentation: doc/sphinx/reference/vmod.rst
+
 ================================
 Varnish Cache 7.5.0 (2024-03-18)
 ================================
diff --git a/doc/sphinx/reference/vmod.rst b/doc/sphinx/reference/vmod.rst
index b8a524ce6..193b9060d 100644
--- a/doc/sphinx/reference/vmod.rst
+++ b/doc/sphinx/reference/vmod.rst
@@ -858,3 +858,47 @@ You should call ``VSC_*_New()`` when your VMOD is loaded and
 ``VSC_*_Destroy()`` when it is unloaded. See the generated
 ``VSC_*.h`` file for the full details about the structure that contains
 your counters.
+
+Temporary Files
+===============
+
+``varnishd`` creates a directroy named ``worker_tmpdir`` under the
+varnish working directory (see ``varnishd -n`` argument) for
+read/write access by the worker process.
+
+From the perspective of VMODs, the relative path is always
+``worker_tmpdir``.
+
+This directory is intended (though not limited) to provide a place for
+VMODs to create temporary files using ``mkstemp()`` and related libc
+functions. VMODs are responsible for cleaning up files which are no
+longer required, and they will ultimately be removed when the
+``varnishd`` worker process restarts. There is no isolation between
+VMODs (as is the case anyway).
+
+A simple example for how to use it::
+
+	#include <stdlib.h>
+	#include <unistd.h>
+
+	#include "vdef.h"
+	#include "vas.h"
+
+	static void
+	tmpfile_example(void) {
+	    int fd;
+	    char name[] = "worker_tmpdir/myvmod.XXXXXX";
+
+	    fd = mkstemp(name);
+	    if (fd < 0) {
+		// handle error
+		return;
+	    }
+
+	    // hide file
+	    AZ(unlink(name));
+
+	    // use fd
+
+	    AZ(close(fd));
+	}
diff --git a/vmod/vmod_debug.c b/vmod/vmod_debug.c
index 8f3f5636e..e2e42ee51 100644
--- a/vmod/vmod_debug.c
+++ b/vmod/vmod_debug.c
@@ -55,6 +55,7 @@ struct priv_vcl {
 	VCL_BACKEND		be;
 	unsigned		cold_be;
 	unsigned		cooling_be;
+	int			tmpf;
 };
 
 
@@ -401,12 +402,18 @@ VCL_VOID v_matchproto_(td_debug_test_priv_vcl)
 xyzzy_test_priv_vcl(VRT_CTX, struct vmod_priv *priv)
 {
 	struct priv_vcl *priv_vcl;
+	char t[PATH_MAX];
+	ssize_t l;
 
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
 	AN(priv);
 	CAST_OBJ_NOTNULL(priv_vcl, priv->priv, PRIV_VCL_MAGIC);
+
+	l = pread(priv_vcl->tmpf, t, sizeof t, 0);
+	assert(l > 0);
+
 	AN(priv_vcl->foo);
-	assert(!strcmp(priv_vcl->foo, "FOO"));
+	assert(!strncmp(priv_vcl->foo, t, l));
 }
 
 VCL_VOID v_matchproto_(td_debug_rot104)
@@ -501,7 +508,9 @@ priv_vcl_fini(VRT_CTX, void *priv)
 	struct priv_vcl *priv_vcl;
 
 	CAST_OBJ_NOTNULL(priv_vcl, priv, PRIV_VCL_MAGIC);
+	AZ(close(priv_vcl->tmpf));
 	AN(priv_vcl->foo);
+	AZ(unlink(priv_vcl->foo));
 	free(priv_vcl->foo);
 	if (priv_vcl->obj_cb != 0) {
 		ObjUnsubscribeEvents(&priv_vcl->obj_cb);
@@ -534,8 +543,11 @@ event_load(VRT_CTX, struct vmod_priv *priv)
 
 	ALLOC_OBJ(priv_vcl, PRIV_VCL_MAGIC);
 	AN(priv_vcl);
-	priv_vcl->foo = strdup("FOO");
+	priv_vcl->foo = strdup("worker_tmpdir/vmod_debug.XXXXXX");
 	AN(priv_vcl->foo);
+	priv_vcl->tmpf = mkstemp(priv_vcl->foo);
+	assert(priv_vcl->tmpf >= 0);
+	AN(write(priv_vcl->tmpf, priv_vcl->foo, strlen(priv_vcl->foo)));
 	priv->priv = priv_vcl;
 	priv->methods = priv_vcl_methods;
 


More information about the varnish-commit mailing list