added shutdownevent for graceful shutdown
diff --git a/apid.go b/apid.go
index 73f243c..7da00d9 100644
--- a/apid.go
+++ b/apid.go
@@ -1,9 +1,12 @@
 package apid
 
-import "os"
+import (
+	"os"
+)
 
 const (
 	SystemEventsSelector EventSelector = "system event"
+	ShutdownEventSelector EventSelector = "shutdown event"
 )
 
 var (
@@ -12,6 +15,8 @@
 
 	pluginInitFuncs []PluginInitFunc
 	services        Services
+
+	shutdownChan chan int
 )
 
 type Services interface {
@@ -44,6 +49,8 @@
 	ss.api = s.API()
 	ss.data = s.Data()
 
+	shutdownChan = make(chan int)
+
 	ss.events.Emit(SystemEventsSelector, APIDInitializedEvent)
 }
 
@@ -69,6 +76,24 @@
 	log.Debugf("done initializing plugins")
 }
 
+func ShutdownPlugins() {
+	Events().EmitWithCallback(ShutdownEventSelector, ShutdownEvent{"apid is going to shutdown"}, ShutdownHandler)
+}
+
+
+func ShutdownHandler(event Event) {
+	log := Log()
+	log.Debugf("shutdown apid")
+	shutdownChan <- 1
+}
+
+/* wait for the shutdown of registered graceful-shutdown plugins, blocking until the required plugins finish shutdown
+ * this is used to prevent the main from exiting
+ */
+func WaitPluginsShutdown() {
+	<- shutdownChan
+}
+
 func AllServices() Services {
 	return services
 }
@@ -124,3 +149,7 @@
 type systemEvent struct {
 	description string
 }
+
+type ShutdownEvent struct {
+	Description string
+}
diff --git a/events/event_manager.go b/events/event_manager.go
index 33b0ee1..12e8f82 100644
--- a/events/event_manager.go
+++ b/events/event_manager.go
@@ -13,7 +13,8 @@
 
 func (em *eventManager) Emit(selector apid.EventSelector, event apid.Event) {
 	log.Debugf("emit selector: '%s' event %v: %v", selector, &event, event)
-	if !em.dispatchers[selector].Send(event) {
+	eventDispatcher := em.dispatchers[selector]
+	if (eventDispatcher==nil) || (!eventDispatcher.Send(event)) {
 		em.sendDelivered(selector, event, 0) // in case of no dispatcher
 	}
 }
diff --git a/events/events_test.go b/events/events_test.go
index 70bc19a..b2e3f9d 100644
--- a/events/events_test.go
+++ b/events/events_test.go
@@ -6,6 +6,8 @@
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 	"sync/atomic"
+	"fmt"
+	"strconv"
 )
 
 var _ = Describe("Events Service", func() {
@@ -287,8 +289,75 @@
 		apid.InitializePlugins()
 	})
 
+	It("shutdown event should be emitted and listened successfully", func(done Done) {
+		h := func(event apid.Event) {
+			defer GinkgoRecover()
+
+			if pie, ok := event.(apid.ShutdownEvent); ok {
+				apid.Events().Close()
+				Expect(pie.Description).Should(Equal("apid is going to shutdown"))
+				fmt.Println(pie.Description)
+				close(done)
+			} else {
+				Fail("Received wrong event")
+			}
+		}
+		apid.Events().ListenFunc(apid.ShutdownEventSelector, h)
+		shutdownHandler := func(event apid.Event) {}
+		apid.Events().EmitWithCallback(apid.ShutdownEventSelector, apid.ShutdownEvent{"apid is going to shutdown"}, shutdownHandler)
+	})
+
+	It("handlers registered by plugins should execute before apid shutdown", func(done Done) {
+		pluginNum := 10
+		count := make([]int, 1)
+		count[0] = 0
+
+		// create and register plugins, listen to shutdown event
+		for i:=0; i<pluginNum; i++ {
+			apid.RegisterPlugin(createDummyPlugin(i))
+			h := func(event apid.Event) {
+				if pie, ok := event.(apid.ShutdownEvent); ok {
+					Expect(pie.Description).Should(Equal("apid is going to shutdown"))
+					count[0] += 1
+				} else {
+					Fail("Received wrong event")
+				}
+			}
+			apid.Events().ListenFunc(apid.ShutdownEventSelector, h)
+		}
+
+
+		apid.InitializePlugins()
+
+		apid.ShutdownPlugins()
+
+		apid.WaitPluginsShutdown()
+
+		defer GinkgoRecover()
+		apid.Events().Close()
+		// handlers of all registered plugins have executed
+		Expect(count[0]).Should(Equal(pluginNum))
+		fmt.Println("handlers of all registered plugins have executed")
+
+		close(done)
+	})
 })
 
+func createDummyPlugin(id int) apid.PluginInitFunc{
+	xData := make(map[string]interface{})
+	xData["schemaVersion"] = "1.2.3"
+	p := func(s apid.Services) (pd apid.PluginData, err error) {
+		pd = apid.PluginData{
+			Name: "test plugin " + strconv.Itoa(id),
+			Version: "1.0.0",
+			ExtraData: xData,
+		}
+		return
+	}
+	return p
+
+}
+
 type test_handler struct {
 	description string
 	f           func(event apid.Event)