diff mbox

[ovs-dev,V5] windows: Added lockf function and lock PID file

Message ID 1467390468-12900-1-git-send-email-pboca@cloudbasesolutions.com
State Superseded
Delegated to: Guru Shetty
Headers show

Commit Message

Paul Boca July 1, 2016, 4:27 p.m. UTC
If the PID file isn't locked then appctl.py detects it as stale and
bails out without doing anything. Because of this lots of Python tests fail.
Also this protects the PID file from being overwritten.

I used only shared lock, in order to be compatible with Python tests,
which try to acquire the lock exclusively. On Windows if the exclusive lock
is used, than the read access is denied too for other instances of this file.

Signed-off-by: Paul-Daniel Boca <pboca@cloudbasesolutions.com>
---
V2: No changes
V3: No changes
V4: No changes
V5: Removed this patch from Python series.
    Removed unused constants and defined 0xFFFF0000 as constant.
    Updated commit text.
---
 lib/daemon-windows.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

Comments

Alin Serdean July 4, 2016, 2:40 p.m. UTC | #1
> -----Mesaj original-----

> De la: dev [mailto:dev-bounces@openvswitch.org] În numele Paul Boca

> Trimis: Friday, July 1, 2016 7:28 PM

> Către: dev@openvswitch.org

> Subiect: [ovs-dev] [PATCH V5] windows: Added lockf function and lock PID

> file

> 

> If the PID file isn't locked then appctl.py detects it as stale and bails out

> without doing anything. Because of this lots of Python tests fail.

> Also this protects the PID file from being overwritten.

> 

> I used only shared lock, in order to be compatible with Python tests, which

> try to acquire the lock exclusively. On Windows if the exclusive lock is used,

> than the read access is denied too for other instances of this file.

> 

> Signed-off-by: Paul-Daniel Boca <pboca@cloudbasesolutions.com>

> +static int

[Alin Gabriel Serdean: ] I don't really understand why 'int' when you are returning -1/0. The problem is: you need to deal with GetLastError and errno if a specific function failed. 
> +flock(FILE* fd, int operation)

> +{

> +    NTSTATUS status;

> +    HANDLE hFile;

> +    OVERLAPPED ov = {0};

> +

> +    hFile = (HANDLE)_get_osfhandle(fileno(filep_pidfile));

[Alin Gabriel Serdean: ] either use fd or drop the parameter fd.
> +    if (hFile == INVALID_HANDLE_VALUE) {

> +        VLOG_FATAL("Invalid handle value");

> +        return -1;

> +    }

> +

> +    if (operation & LOCK_UN) {

> +        if (UnlockFileEx(hFile, 0, 0, LOCK_MAX_SIZE, &ov) == FALSE) {

[Alin Gabriel Serdean: ] According to the docs UnlockFileEx can be 0 or NULL
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365716(v=vs.85).aspx

> +            return -1;

> +        }

> +    } else {

> +        if (LockFileEx(hFile, operation, 0, 0, LOCK_MAX_SIZE, &ov) == FALSE) {

> +            VLOG_FATAL("LockFileEx failed, status = 0x%08x\n", status);

> +            return -1;

> +        }

> +    }

> +

> +    return 0;

> +}

> +

>  /* If a pidfile has been configured, creates it and stores the running

>   * process's pid in it.  Ensures that the pidfile will be deleted when the

>   * process exits. */

> @@ -444,6 +479,14 @@ make_pidfile(void)

>          VLOG_FATAL("Failed to write into the pidfile %s", pidfile);

>      }

> 

[Alin Gabriel Serdean: ] Unless I am missing something: there is another call to fflush just above, do we need to flush the buffers again?
> +    fflush(filep_pidfile);

> +    error = flock(filep_pidfile, LOCK_SH);

> +    if (error) {

> +        /* Looks like we failed to acquire the lock. */

> +        VLOG_FATAL("%s: fcntl(F_SETLK) failed (%s)", pidfile,

> +                   ovs_strerror(error));

> +    }

> +

>      /* Don't close the pidfile till the process exits. */  }

> 

> --

> 2.7.2.windows.1

> _______________________________________________

> dev mailing list

> dev@openvswitch.org

> http://openvswitch.org/mailman/listinfo/dev
Paul Boca July 4, 2016, 2:45 p.m. UTC | #2
Hi Alin!

Thanks for review. You are right with all the observations.
I will send another patch that will fix them.

Thanks,
Paul

> -----Original Message-----

> From: Alin Serdean

> Sent: Monday, July 4, 2016 5:41 PM

> To: Paul Boca; dev@openvswitch.org

> Subject: RE: [PATCH V5] windows: Added lockf function and lock PID file

> 

> > -----Mesaj original-----

> > De la: dev [mailto:dev-bounces@openvswitch.org] În numele Paul Boca

> > Trimis: Friday, July 1, 2016 7:28 PM

> > Către: dev@openvswitch.org

> > Subiect: [ovs-dev] [PATCH V5] windows: Added lockf function and lock PID

> > file

> >

> > If the PID file isn't locked then appctl.py detects it as stale and bails out

> > without doing anything. Because of this lots of Python tests fail.

> > Also this protects the PID file from being overwritten.

> >

> > I used only shared lock, in order to be compatible with Python tests, which

> > try to acquire the lock exclusively. On Windows if the exclusive lock is used,

> > than the read access is denied too for other instances of this file.

> >

> > Signed-off-by: Paul-Daniel Boca <pboca@cloudbasesolutions.com>

> > +static int

> [Alin Gabriel Serdean: ] I don't really understand why 'int' when you are

> returning -1/0. The problem is: you need to deal with GetLastError and errno

> if a specific function failed.

> > +flock(FILE* fd, int operation)

> > +{

> > +    NTSTATUS status;

> > +    HANDLE hFile;

> > +    OVERLAPPED ov = {0};

> > +

> > +    hFile = (HANDLE)_get_osfhandle(fileno(filep_pidfile));

> [Alin Gabriel Serdean: ] either use fd or drop the parameter fd.

> > +    if (hFile == INVALID_HANDLE_VALUE) {

> > +        VLOG_FATAL("Invalid handle value");

> > +        return -1;

> > +    }

> > +

> > +    if (operation & LOCK_UN) {

> > +        if (UnlockFileEx(hFile, 0, 0, LOCK_MAX_SIZE, &ov) == FALSE) {

> [Alin Gabriel Serdean: ] According to the docs UnlockFileEx can be 0 or NULL

> https://msdn.microsoft.com/en-

> us/library/windows/desktop/aa365716(v=vs.85).aspx

> 

> > +            return -1;

> > +        }

> > +    } else {

> > +        if (LockFileEx(hFile, operation, 0, 0, LOCK_MAX_SIZE, &ov) == FALSE) {

> > +            VLOG_FATAL("LockFileEx failed, status = 0x%08x\n", status);

> > +            return -1;

> > +        }

> > +    }

> > +

> > +    return 0;

> > +}

> > +

> >  /* If a pidfile has been configured, creates it and stores the running

> >   * process's pid in it.  Ensures that the pidfile will be deleted when the

> >   * process exits. */

> > @@ -444,6 +479,14 @@ make_pidfile(void)

> >          VLOG_FATAL("Failed to write into the pidfile %s", pidfile);

> >      }

> >

> [Alin Gabriel Serdean: ] Unless I am missing something: there is another call

> to fflush just above, do we need to flush the buffers again?

> > +    fflush(filep_pidfile);

> > +    error = flock(filep_pidfile, LOCK_SH);

> > +    if (error) {

> > +        /* Looks like we failed to acquire the lock. */

> > +        VLOG_FATAL("%s: fcntl(F_SETLK) failed (%s)", pidfile,

> > +                   ovs_strerror(error));

> > +    }

> > +

> >      /* Don't close the pidfile till the process exits. */  }

> >

> > --

> > 2.7.2.windows.1

> > _______________________________________________

> > dev mailing list

> > dev@openvswitch.org

> > http://openvswitch.org/mailman/listinfo/dev
Ben Pfaff July 4, 2016, 3:05 p.m. UTC | #3
On Fri, Jul 01, 2016 at 04:27:49PM +0000, Paul Boca wrote:
> If the PID file isn't locked then appctl.py detects it as stale and
> bails out without doing anything. Because of this lots of Python tests fail.
> Also this protects the PID file from being overwritten.
> 
> I used only shared lock, in order to be compatible with Python tests,
> which try to acquire the lock exclusively. On Windows if the exclusive lock
> is used, than the read access is denied too for other instances of this file.
> 
> Signed-off-by: Paul-Daniel Boca <pboca@cloudbasesolutions.com>

I'm still not sure that real locking is actually needed for Windows.
I believe that, on Windows, the functionality of a lock file only
requires holding the file open.  For a program to detect whether the
lock file is locked, it can just try to delete it; on Windows, I believe
that deleting an open file fails.
Alin Serdean July 4, 2016, 3:21 p.m. UTC | #4
> > I used only shared lock, in order to be compatible with Python tests,

> > which try to acquire the lock exclusively. On Windows if the exclusive

> > lock is used, than the read access is denied too for other instances of this

> file.

> >

> > Signed-off-by: Paul-Daniel Boca <pboca@cloudbasesolutions.com>

> 

> I'm still not sure that real locking is actually needed for Windows.

> I believe that, on Windows, the functionality of a lock file only requires

> holding the file open.  For a program to detect whether the lock file is locked,

> it can just try to delete it; on Windows, I believe that deleting an open file

> fails.

[Alin Gabriel Serdean: ] That is correct Ben. But think about somebody which is using python and coming from a Unix environment, he will try to read/write to the locked file. In my opinion we should try to mimic that behavior.
> _______________________________________________

> dev mailing list

> dev@openvswitch.org

> http://openvswitch.org/mailman/listinfo/dev
Alin Serdean July 4, 2016, 6:02 p.m. UTC | #5
> > I'm still not sure that real locking is actually needed for Windows.

> > I believe that, on Windows, the functionality of a lock file only

> > requires holding the file open.  For a program to detect whether the

> > lock file is locked, it can just try to delete it; on Windows, I

> > believe that deleting an open file fails.

> [Alin Gabriel Serdean: ] That is correct Ben. But think about somebody which

> is using python and coming from a Unix environment, he will try to

> read/write to the locked file. In my opinion we should try to mimic that

> behavior.

Another problem would be we can write over the pid file and if we try to do something like
$a = type .\ovs-vswitchd.pid
taskkill.exe /PID $a /F
Would be bogus because someone could have changed it.

Alin.
Ben Pfaff July 4, 2016, 9:26 p.m. UTC | #6
On Mon, Jul 04, 2016 at 06:02:31PM +0000, Alin Serdean wrote:
> > > I'm still not sure that real locking is actually needed for Windows.
> > > I believe that, on Windows, the functionality of a lock file only
> > > requires holding the file open.  For a program to detect whether the
> > > lock file is locked, it can just try to delete it; on Windows, I
> > > believe that deleting an open file fails.
> > [Alin Gabriel Serdean: ] That is correct Ben. But think about somebody which
> > is using python and coming from a Unix environment, he will try to
> > read/write to the locked file. In my opinion we should try to mimic that
> > behavior.
> Another problem would be we can write over the pid file and if we try to do something like
> $a = type .\ovs-vswitchd.pid
> taskkill.exe /PID $a /F
> Would be bogus because someone could have changed it.

It's OK with me if we actually lock the lockfiles, it just seems less
necessary on Windows.
diff mbox

Patch

diff --git a/lib/daemon-windows.c b/lib/daemon-windows.c
index 8cf0fea..4c4724b 100644
--- a/lib/daemon-windows.c
+++ b/lib/daemon-windows.c
@@ -18,6 +18,7 @@ 
 #include "daemon.h"
 #include "daemon-private.h"
 #include <stdio.h>
+#include <io.h>
 #include <stdlib.h>
 #include "dirs.h"
 #include "ovs-thread.h"
@@ -26,6 +27,13 @@ 
 
 VLOG_DEFINE_THIS_MODULE(daemon_windows);
 
+/* Constants for flock function */
+#define	LOCK_SH	0x0                         /* Shared lock. */
+#define	LOCK_UN	0x80000000                  /* Unlock. Custom value. */
+
+/* High-order 32 bits of byte range to lock */
+#define LOCK_MAX_SIZE 0xFFFF0000
+
 static bool service_create;          /* Was --service specified? */
 static bool service_started;         /* Have we dispatched service to start? */
 
@@ -414,6 +422,33 @@  unlink_pidfile(void)
     }
 }
 
+static int
+flock(FILE* fd, int operation)
+{
+    NTSTATUS status;
+    HANDLE hFile;
+    OVERLAPPED ov = {0};
+
+    hFile = (HANDLE)_get_osfhandle(fileno(filep_pidfile));
+    if (hFile == INVALID_HANDLE_VALUE) {
+        VLOG_FATAL("Invalid handle value");
+        return -1;
+    }
+
+    if (operation & LOCK_UN) {
+        if (UnlockFileEx(hFile, 0, 0, LOCK_MAX_SIZE, &ov) == FALSE) {
+            return -1;
+        }
+    } else {
+        if (LockFileEx(hFile, operation, 0, 0, LOCK_MAX_SIZE, &ov) == FALSE) {
+            VLOG_FATAL("LockFileEx failed, status = 0x%08x\n", status);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
 /* If a pidfile has been configured, creates it and stores the running
  * process's pid in it.  Ensures that the pidfile will be deleted when the
  * process exits. */
@@ -444,6 +479,14 @@  make_pidfile(void)
         VLOG_FATAL("Failed to write into the pidfile %s", pidfile);
     }
 
+    fflush(filep_pidfile);
+    error = flock(filep_pidfile, LOCK_SH);
+    if (error) {
+        /* Looks like we failed to acquire the lock. */
+        VLOG_FATAL("%s: fcntl(F_SETLK) failed (%s)", pidfile,
+                   ovs_strerror(error));
+    }
+
     /* Don't close the pidfile till the process exits. */
 }