From c0f6149926119fdf300cd07863712146802fa22a Mon Sep 17 00:00:00 2001 From: Hristo Venev Date: Mon, 7 Mar 2016 14:07:43 +0200 Subject: [PATCH 2/2] fcntl: Support Linux open file descriptor locks - Add open_file_descriptor argument to lockf - Add F_OFD_{GETLK,SETLK,SETLKW} --- Lib/test/test_fcntl.py | 19 +++++++++++++++++++ Modules/fcntlmodule.c | 27 +++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index e3b7ed2..c54b5cd 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -11,6 +11,11 @@ from test.support import (verbose, TESTFN, unlink, run_unittest, import_module, # Skip test if no fcntl module. fcntl = import_module('fcntl') +class NotInt: + def __init__(self, a): + self.a=a + def __int__(self): + return self.a # TODO - Write tests for flock() and lockf(). @@ -134,6 +139,20 @@ class TestFcntl(unittest.TestCase): fcntl.flock(self.f, fcntl.LOCK_UN) fcntl.flock(fileno, fcntl.LOCK_EX) fcntl.flock(fileno, fcntl.LOCK_UN) + fcntl.lockf(fileno, fcntl.LOCK_EX, 2**31-1) + fcntl.lockf(fileno, fcntl.LOCK_EX, 2**31) + fcntl.lockf(fileno, fcntl.LOCK_EX, NotInt(2**31-1)) + fcntl.lockf(fileno, fcntl.LOCK_EX, NotInt(2**31)) + self.assertRaises(BlockingIOError, fcntl.lockf, fileno, fcntl.LOCK_EX | fcntl.LOCK_NB, open_file_descriptor=True) + fcntl.lockf(fileno, fcntl.LOCK_UN) + fcntl.lockf(fileno, fcntl.LOCK_SH) + fcntl.lockf(fileno, fcntl.LOCK_SH | fcntl.LOCK_NB) + fcntl.lockf(fileno, fcntl.LOCK_SH | fcntl.LOCK_NB, open_file_descriptor=True) + fcntl.lockf(fileno, fcntl.LOCK_SH | fcntl.LOCK_NB, open_file_descriptor=True) + self.assertRaises(BlockingIOError, fcntl.lockf, fileno, fcntl.LOCK_EX | fcntl.LOCK_NB, open_file_descriptor=True) + fcntl.lockf(fileno, fcntl.LOCK_UN) + fcntl.lockf(fileno, fcntl.LOCK_EX | fcntl.LOCK_NB, open_file_descriptor=True) + fcntl.lockf(fileno, fcntl.LOCK_UN, open_file_descriptor=True) self.assertRaises(ValueError, fcntl.flock, -1, fcntl.LOCK_SH) self.assertRaises(TypeError, fcntl.flock, 'spam', fcntl.LOCK_SH) diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c index 1875326..b100498 100644 --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -331,7 +331,7 @@ fcntl.lockf len as lenobj: object(c_default='NULL') = 0 start as startobj: object(c_default='NULL') = 0 whence: int = 0 - / + open_file_descriptor: bool = False A wrapper around the fcntl() locking calls. @@ -359,8 +359,8 @@ starts. `whence` is as with fileobj.seek(), specifically: static PyObject * fcntl_lockf_impl(PyModuleDef *module, int fd, int code, PyObject *lenobj, - PyObject *startobj, int whence) -/*[clinic end generated code: output=31af35eba08b9af7 input=9c594391de821f24]*/ + PyObject *startobj, int whence, int open_file_descriptor) +/*[clinic end generated code: output=35b767f635507cd4 input=57433c68e144e94b]*/ { int ret; @@ -403,8 +403,18 @@ fcntl_lockf_impl(PyModuleDef *module, int fd, int code, PyObject *lenobj, return NULL; } l.l_whence = whence; + l.l_pid = 0; Py_BEGIN_ALLOW_THREADS - ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l); + if (open_file_descriptor) { +#ifdef F_OFD_SETLK + ret = fcntl(fd, (code & LOCK_NB) ? F_OFD_SETLK : F_OFD_SETLKW, &l); +#else + PyErr_SetString(PyExc_NotImplementedError, + "lockf: open_file_descriptor not supported on this platform"); + return NULL; +#endif + } else + ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l); Py_END_ALLOW_THREADS } if (ret < 0) { @@ -482,6 +492,15 @@ all_ins(PyObject* m) #ifdef F_SETLKW if (PyModule_AddIntMacro(m, F_SETLKW)) return -1; #endif +#ifdef F_OFD_GETLK + if (PyModule_AddIntMacro(m, F_OFD_GETLK)) return -1; +#endif +#ifdef F_OFD_SETLK + if (PyModule_AddIntMacro(m, F_OFD_SETLK)) return -1; +#endif +#ifdef F_OFD_SETLKW + if (PyModule_AddIntMacro(m, F_OFD_SETLKW)) return -1; +#endif #ifdef F_GETOWN if (PyModule_AddIntMacro(m, F_GETOWN)) return -1; #endif -- 2.7.2