diff --git a/serial.go b/serial.go
index 64e5b8f7..1a43f364 100755
--- a/serial.go
+++ b/serial.go
@@ -31,7 +31,7 @@ import (
 
 type serialhub struct {
 	// Opened serial ports.
-	ports map[*serport]bool
+	ports map[string]*serport
 
 	mu sync.Mutex
 }
@@ -60,7 +60,7 @@ type SpPortItem struct {
 var serialPorts SerialPortList
 
 var sh = serialhub{
-	ports: make(map[*serport]bool),
+	ports: make(map[string]*serport),
 }
 
 // Register serial ports from the connections.
@@ -68,7 +68,7 @@ func (sh *serialhub) Register(port *serport) {
 	sh.mu.Lock()
 	//log.Print("Registering a port: ", p.portConf.Name)
 	h.broadcastSys <- []byte("{\"Cmd\":\"Open\",\"Desc\":\"Got register/open on port.\",\"Port\":\"" + port.portConf.Name + "\",\"Baud\":" + strconv.Itoa(port.portConf.Baud) + ",\"BufferType\":\"" + port.BufferType + "\"}")
-	sh.ports[port] = true
+	sh.ports[port.portName] = port
 	sh.mu.Unlock()
 }
 
@@ -77,7 +77,7 @@ func (sh *serialhub) Unregister(port *serport) {
 	sh.mu.Lock()
 	//log.Print("Unregistering a port: ", p.portConf.Name)
 	h.broadcastSys <- []byte("{\"Cmd\":\"Close\",\"Desc\":\"Got unregister/close on port.\",\"Port\":\"" + port.portConf.Name + "\",\"Baud\":" + strconv.Itoa(port.portConf.Baud) + "}")
-	delete(sh.ports, port)
+	delete(sh.ports, port.portName)
 	close(port.sendBuffered)
 	close(port.sendNoBuf)
 	sh.mu.Unlock()
@@ -86,15 +86,8 @@ func (sh *serialhub) Unregister(port *serport) {
 func (sh *serialhub) FindPortByName(portname string) (*serport, bool) {
 	sh.mu.Lock()
 	defer sh.mu.Unlock()
-
-	for port := range sh.ports {
-		if strings.EqualFold(port.portConf.Name, portname) {
-			// we found our port
-			//spHandlerClose(port)
-			return port, true
-		}
-	}
-	return nil, false
+	port, ok := sh.ports[portname]
+	return port, ok
 }
 
 // List broadcasts a Json representation of the ports found
diff --git a/serialport.go b/serialport.go
index 0d386bbf..b3418fe5 100755
--- a/serialport.go
+++ b/serialport.go
@@ -20,6 +20,7 @@ import (
 	"encoding/base64"
 	"io"
 	"strconv"
+	"sync"
 	"sync/atomic"
 	"time"
 	"unicode/utf8"
@@ -273,7 +274,13 @@ func (p *serport) writerRaw() {
 	h.broadcastSys <- []byte(msgstr)
 }
 
+// This lock is used to prevent multiple threads from trying to open the same port at the same time.
+// It presents issues with the serial port driver on some OS's: https://github.com/arduino/arduino-create-agent/issues/1031
+var spHandlerOpenLock sync.Mutex
+
 func spHandlerOpen(portname string, baud int, buftype string) {
+	spHandlerOpenLock.Lock()
+	defer spHandlerOpenLock.Unlock()
 
 	log.Print("Inside spHandler")
 
@@ -295,11 +302,14 @@ func spHandlerOpen(portname string, baud int, buftype string) {
 	sp, err := serial.Open(portname, mode)
 	log.Print("Just tried to open port")
 	if err != nil {
-		//log.Fatal(err)
-		log.Print("Error opening port " + err.Error())
-		//h.broadcastSys <- []byte("Error opening port. " + err.Error())
-		h.broadcastSys <- []byte("{\"Cmd\":\"OpenFail\",\"Desc\":\"Error opening port. " + err.Error() + "\",\"Port\":\"" + conf.Name + "\",\"Baud\":" + strconv.Itoa(conf.Baud) + "}")
-
+		existingPort, ok := sh.FindPortByName(portname)
+		if ok && existingPort.portConf.Baud == baud && existingPort.BufferType == buftype {
+			log.Print("Port already opened")
+			h.broadcastSys <- []byte("{\"Cmd\":\"Open\",\"Desc\":\"Port already opened.\",\"Port\":\"" + existingPort.portConf.Name + "\",\"Baud\":" + strconv.Itoa(existingPort.portConf.Baud) + ",\"BufferType\":\"" + existingPort.BufferType + "\"}")
+		} else {
+			log.Print("Error opening port " + err.Error())
+			h.broadcastSys <- []byte("{\"Cmd\":\"OpenFail\",\"Desc\":\"Error opening port. " + err.Error() + "\",\"Port\":\"" + conf.Name + "\",\"Baud\":" + strconv.Itoa(conf.Baud) + "}")
+		}
 		return
 	}
 	log.Print("Opened port successfully")
@@ -331,7 +341,6 @@ func spHandlerOpen(portname string, baud int, buftype string) {
 	p.bufferwatcher = bw
 
 	sh.Register(p)
-	defer sh.Unregister(p)
 
 	serialPorts.MarkPortAsOpened(portname)
 	serialPorts.List()
@@ -342,10 +351,12 @@ func spHandlerOpen(portname string, baud int, buftype string) {
 	go p.writerNoBuf()
 	// this is thread to send to serial port but with base64 decoding
 	go p.writerRaw()
-
-	p.reader(buftype)
-
-	serialPorts.List()
+	// this is the thread that reads from the serial port
+	go func() {
+		p.reader(buftype)
+		serialPorts.List()
+		sh.Unregister(p)
+	}()
 }
 
 func (p *serport) Close() {