os: make Process.Signal 'process finished' error consistent on Unix

While we're here, fix the implementation of Release on both
Unix and Windows: Release is supposed to make Signal an error.

While we're here, make sure we never Signal pid 0.
(Don't try this at home.)

Fixes #7658.

LGTM=r
R=golang-codereviews, r
CC=golang-codereviews, iant
https://golang.org/cl/152240043
diff --git a/src/os/exec_unix.go b/src/os/exec_unix.go
index 1b1e335..ed97f85 100644
--- a/src/os/exec_unix.go
+++ b/src/os/exec_unix.go
@@ -34,18 +34,26 @@
 	return ps, nil
 }
 
+var errFinished = errors.New("os: process already finished")
+
 func (p *Process) signal(sig Signal) error {
-	if p.done() {
-		return errors.New("os: process already finished")
-	}
 	if p.Pid == -1 {
 		return errors.New("os: process already released")
 	}
+	if p.Pid == 0 {
+		return errors.New("os: process not initialized")
+	}
+	if p.done() {
+		return errFinished
+	}
 	s, ok := sig.(syscall.Signal)
 	if !ok {
 		return errors.New("os: unsupported signal type")
 	}
 	if e := syscall.Kill(p.Pid, s); e != nil {
+		if e == syscall.ESRCH {
+			return errFinished
+		}
 		return e
 	}
 	return nil
diff --git a/src/os/exec_windows.go b/src/os/exec_windows.go
index c4f3d4f..393393b 100644
--- a/src/os/exec_windows.go
+++ b/src/os/exec_windows.go
@@ -53,6 +53,9 @@
 }
 
 func (p *Process) signal(sig Signal) error {
+	if p.handle == uintptr(syscall.InvalidHandle) {
+		return syscall.EINVAL
+	}
 	if p.done() {
 		return errors.New("os: process already finished")
 	}