# Check for realpath().
AC_CHECK_FUNC([realpath], [AC_DEFINE(HAVE_REALPATH, 1, [realpath is available.])], [])
+# Check for flock().
+AC_CHECK_HEADER([sys/file.h], [AC_DEFINE(HAVE_SYS_FILE_H, 1, [sys/file.h is available.])], [])
+AC_CHECK_FUNC([flock], [AC_DEFINE(HAVE_FLOCK, 1, [flock is available.])], [])
+
# Check for clock_gettime().
AC_CHECK_FUNC([clock_gettime],
[AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [clock_gettime is available.])], [])
if ((port->fd = open(port->name, flags_local)) < 0)
RETURN_FAIL("open() failed");
+
+ /*
+ * On POSIX in the default case the file descriptor of a serial port
+ * is not opened exclusively. Therefore the settings of a port are
+ * overwritten if the serial port is opened a second time. Windows
+ * opens all serial ports exclusively.
+ * So the idea is to open the serial ports alike in the exclusive mode.
+ *
+ * ioctl(*, TIOCEXCL) defines the file descriptor as exclusive. So all
+ * further open calls on the serial port will fail.
+ *
+ * There is a race condition if two processes open the same serial
+ * port. None of the processes will notice the exclusive ownership of
+ * the other process because ioctl() doesn't return an error code if
+ * the file descriptor is already marked as exclusive.
+ * This can be solved with flock(). It returns an error if the file
+ * descriptor is already locked by another process.
+ */
+#ifdef HAVE_FLOCK
+ if (flock(port->fd, LOCK_EX | LOCK_NB) < 0)
+ RETURN_FAIL("flock() failed");
+#endif
+
+#ifdef TIOCEXCL
+ /*
+ * Before Linux 3.8 ioctl(*, TIOCEXCL) was not implemented and could
+ * lead to EINVAL or ENOTTY.
+ * These errors aren't fatal and can be ignored.
+ */
+ if (ioctl(port->fd, TIOCEXCL) < 0 && errno != EINVAL && errno != ENOTTY)
+ RETURN_FAIL("ioctl() failed");
+#endif
+
#endif
ret = get_config(port, &data, &config);