diff --git a/contrib/say_hello/Makefile b/contrib/say_hello/Makefile
new file mode 100644
index 0000000..2da89d7
--- /dev/null
+++ b/contrib/say_hello/Makefile
@@ -0,0 +1,17 @@
+# contrib/say_hello/Makefile
+
+MODULES = say_hello
+
+EXTENSION = say_hello
+DATA = say_hello--1.0.sql
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/say_hello
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/say_hello/say_hello--1.0.sql b/contrib/say_hello/say_hello--1.0.sql
new file mode 100644
index 0000000..c82b7df
--- /dev/null
+++ b/contrib/say_hello/say_hello--1.0.sql
@@ -0,0 +1,9 @@
+/* contrib/say_hello/say_hello--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION say_hello" to load this file. \quit
+
+CREATE FUNCTION say_hello_launch()
+RETURNS pg_catalog.int4 STRICT
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
diff --git a/contrib/say_hello/say_hello.c b/contrib/say_hello/say_hello.c
new file mode 100644
index 0000000..15b1daf
--- /dev/null
+++ b/contrib/say_hello/say_hello.c
@@ -0,0 +1,110 @@
+/* -------------------------------------------------------------------------
+ *
+ * say_hello.c
+ *
+ * A background worker that just says hello.
+ *
+ * Copyright (C) 2013, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		contrib/say_hello/say_hello.c
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "fmgr.h"
+#include "miscadmin.h"
+#include "postmaster/bgworker.h"
+#include "storage/ipc.h"
+#include "utils/builtins.h"
+#include "utils/guc.h"
+
+PG_MODULE_MAGIC;
+
+PG_FUNCTION_INFO_V1(say_hello_launch);
+
+void		_PG_init(void);
+void		say_hello_main(Datum);
+
+static volatile sig_atomic_t got_sighup = false;
+
+static void
+say_hello_sighup(SIGNAL_ARGS)
+{
+	got_sighup = true;
+}
+
+static void
+say_hello_sigterm(SIGNAL_ARGS)
+{
+	exit(1);
+}
+
+void
+say_hello_main(Datum main_arg)
+{
+	pqsignal(SIGHUP, say_hello_sighup);
+	pqsignal(SIGTERM, say_hello_sigterm);
+	BackgroundWorkerUnblockSignals();
+
+	while (1)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		elog(LOG, "hello!");
+
+		pg_usleep(5 * 1000000L);
+
+		if (got_sighup)
+		{
+			got_sighup = false;
+			ProcessConfigFile(PGC_SIGHUP);
+		}
+	}
+
+	proc_exit(1);
+}
+
+/*
+ * Dynamically launch a worker.
+ */
+Datum
+say_hello_launch(PG_FUNCTION_ARGS)
+{
+	int32		i = PG_GETARG_INT32(0);
+	BackgroundWorker worker;
+	BackgroundWorkerHandle *handle;
+	BgwHandleStatus status;
+	pid_t		pid;
+
+	worker.bgw_flags = 0;
+	worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
+	worker.bgw_restart_time = BGW_NEVER_RESTART;
+	worker.bgw_main = NULL;		/* new worker might not have library loaded */
+	sprintf(worker.bgw_library_name, "say_hello");
+	sprintf(worker.bgw_function_name, "say_hello_main");
+	sprintf(worker.bgw_name, "say_hello");
+	worker.bgw_main_arg = Int32GetDatum(i);
+	/* set bgw_notify_pid so that we can use WaitForBackgroundWorkerStartup */
+	worker.bgw_notify_pid = MyProcPid;
+
+	if (!RegisterDynamicBackgroundWorker(&worker, &handle))
+		PG_RETURN_NULL();
+
+	status = WaitForBackgroundWorkerStartup(handle, &pid);
+
+	if (status == BGWH_STOPPED)
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
+				 errmsg("could not start background process"),
+			   errhint("More details may be available in the server log.")));
+	if (status == BGWH_POSTMASTER_DIED)
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
+			  errmsg("cannot start background processes without postmaster"),
+				 errhint("Kill all remaining database processes and restart the database.")));
+	Assert(status == BGWH_STARTED);
+
+	PG_RETURN_INT32(pid);
+}
diff --git a/contrib/say_hello/say_hello.control b/contrib/say_hello/say_hello.control
new file mode 100644
index 0000000..85044c1
--- /dev/null
+++ b/contrib/say_hello/say_hello.control
@@ -0,0 +1,5 @@
+# say_hello extension
+comment = 'Background worker that just says hello'
+default_version = '1.0'
+module_pathname = '$libdir/say_hello'
+relocatable = true
