Skip to content

Commit

Permalink
Try to use flock first to avoid the bugs in fcntl.
Browse files Browse the repository at this point in the history
  • Loading branch information
zhengshuxin committed Apr 24, 2024
1 parent a30e1e6 commit 0e96092
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 14 deletions.
7 changes: 3 additions & 4 deletions lib_acl/src/stdlib/acl_myflock.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ int acl_myflock(ACL_FILE_HANDLE fd, int lock_style, int operation)
#endif

/*
* fcntl() is standard and does more than we need, but we can handle
* it.
* fcntl() is standard and does more than we need, but we can handle it.
*/
#ifdef ACL_HAS_FCNTL_LOCK
case ACL_FLOCK_STYLE_FCNTL:
Expand Down Expand Up @@ -105,7 +104,7 @@ int acl_myflock(ACL_FILE_HANDLE fd, int lock_style, int operation)
acl_set_error(ACL_EAGAIN);
}

return (status);
return status;
}
#endif /* ACL_UNIX */

Expand Down Expand Up @@ -152,7 +151,7 @@ int acl_myflock(ACL_FILE_HANDLE fd, int lock_style acl_unused, int operation)
}

acl_msg_error("%s(%d): invalid lock_op(%d)", myname, __LINE__, lock_op);
return (-1);
return -1;
}
# else
/* use LockFileEx/UnlockFileEx */
Expand Down
30 changes: 20 additions & 10 deletions lib_acl_cpp/src/stream/fstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,14 @@ bool fstream::lock(bool exclude /* = true */)
return false;
}

int ret = acl_myflock(fd, ACL_FLOCK_STYLE_FCNTL,
exclude ? ACL_FLOCK_OP_EXCLUSIVE : ACL_FLOCK_OP_SHARED);
return ret == 0;
#ifdef ACL_HAS_FLOCK_LOCK
// Use flock mode first when flock is supported by OS.
return acl_myflock(fd, ACL_FLOCK_STYLE_FLOCK,
exclude ? LOCK_EX : LOCK_SH) == 0;
#else
return acl_myflock(fd, ACL_FLOCK_STYLE_FCNTL,
exclude ? ACL_FLOCK_OP_EXCLUSIVE : ACL_FLOCK_OP_SHARED) == 0;
#endif
}

bool fstream::try_lock(bool exclude /* = true */)
Expand All @@ -231,13 +236,14 @@ bool fstream::try_lock(bool exclude /* = true */)
return false;
}

int oper =ACL_FLOCK_OP_NOWAIT;
if (exclude) {
oper |= ACL_FLOCK_OP_EXCLUSIVE;
} else {
oper |= ACL_FLOCK_OP_SHARED;
}
return acl_myflock(fd, ACL_FLOCK_STYLE_FCNTL, oper) == 0;
#ifdef ACL_HAS_FLOCK_LOCK
return acl_myflock(fd, ACL_FLOCK_STYLE_FLOCK,
exclude ? (LOCK_EX | LOCK_NB) : (LOCK_SH | LOCK_NB)) == 0;
#else
return acl_myflock(fd, ACL_FLOCK_STYLE_FCNTL,
exclude ? (ACL_FLOCK_OP_NOWAIT | ACL_FLOCK_OP_EXCLUSIVE)
: (ACL_FLOCK_OP_NOWAIT | ACL_FLOCK_OP_SHARED)) == 0;
#endif
}

bool fstream::unlock(void)
Expand All @@ -251,7 +257,11 @@ bool fstream::unlock(void)
return false;
}

#ifdef ACL_HAS_FLOCK_LOCK
return acl_myflock(fd, ACL_FLOCK_STYLE_FLOCK, ACL_FLOCK_OP_NONE) == 0;
#else
return acl_myflock(fd, ACL_FLOCK_STYLE_FCNTL, ACL_FLOCK_OP_NONE) == 0;
#endif
}

} // namespace acl
3 changes: 3 additions & 0 deletions lib_fiber/samples/file_lock/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include ../Makefile_cpp.in
CFLAGS += -DUSE_FIBER
PROG = file_lock
147 changes: 147 additions & 0 deletions lib_fiber/samples/file_lock/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>

class locker {
public:
locker(const char* filepath, bool close_reader, int sleep_s)
: filepath_(filepath), close_reader_(close_reader), sleep_s_(sleep_s) {}
~locker() {}

void run() {
if (!fp_.open(filepath_, O_RDWR | O_CREAT, 0600)) {
printf("open %s error\r\n", filepath_.c_str());
return;
}

if (!fp_.try_lock()) {
printf("lock %s error %s\r\n", filepath_.c_str(), acl::last_serror());
return;
}

printf("lock %s ok\r\n", filepath_.c_str());

acl::ifstream reader;
if (reader.open_read(filepath_)) {
printf("open_read %s ok\r\n", filepath_.c_str());
} else {
printf("open_read %s error\r\n", filepath_.c_str());
}

if (close_reader_) {
reader.close();
}

::sleep(sleep_s_);

if (!fp_.unlock()) {
printf("Unlock %s error %s\r\n", filepath_.c_str(), acl::last_serror());
} else {
printf("Unlock %s ok\r\n", filepath_.c_str());
}

::sleep(sleep_s_);
}

private:
acl::string filepath_;
bool close_reader_;
int sleep_s_;

acl::fstream fp_;
};

#ifdef USE_FIBER
class fiber_locker : public acl::fiber {
public:
fiber_locker(const char* filepath, bool close_reader, int sleep_s)
: filepath_(filepath), close_reader_(close_reader), sleep_s_(sleep_s) {}
~fiber_locker() {}

protected:
// @override
void run() {
printf("Running in fiber mode\r\n");
locker lk(filepath_, close_reader_, sleep_s_);
lk.run();
}

private:
acl::string filepath_;
bool close_reader_;
int sleep_s_;
};
#endif

class thread_locker : public acl::thread {
public:
thread_locker(const char* filepath, bool close_reader, int sleep_s)
: filepath_(filepath), close_reader_(close_reader), sleep_s_(sleep_s) {}
~thread_locker() {}

protected:
// @override
void* run() {
printf("Running in thread mode\r\n");
locker lk(filepath_, close_reader_, sleep_s_);
lk.run();
return NULL;
}

private:
acl::string filepath_;
bool close_reader_;
int sleep_s_;
};

static void usage(const char* procname) {
printf("usage: %s -h [help]\r\n"
" -t [if using thread mode, default: false]\r\n"
" -c [if closing reader, default: false]\r\n"
" -w sleep_time[default: 5]\r\n", procname);
}

int main(int argc, char* argv[]) {
int ch, sleep_s = 5;
bool use_thread = false, close_reader = false;

while ((ch = getopt(argc, argv, "htcw:")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
return 0;
case 't':
use_thread = true;
break;
case 'c':
close_reader = true;
break;
case 'w':
sleep_s = atoi(optarg);
if (sleep_s <= 0) {
sleep_s = 5;
}
break;
default:
break;
}
}

acl::acl_cpp_init();
acl::log::stdout_open(true);

if (use_thread) {
thread_locker lk("./dummy.lock", close_reader, sleep_s);
lk.start();
lk.wait();
} else {
#ifdef USE_FIBER
acl::fiber::stdout_open(true);
fiber_locker lk("./dummy.lock", close_reader, sleep_s);
lk.start();
acl::fiber::schedule();
#endif
}

return 0;
}
8 changes: 8 additions & 0 deletions lib_fiber/samples/file_lock/stdafx.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// stdafx.cpp : 只包括标准包含文件的源文件
// master_threads.pch 将成为预编译头
// stdafx.obj 将包含预编译类型信息

#include "stdafx.h"

// TODO: 在 STDAFX.H 中
//引用任何所需的附加头文件,而不是在此文件中引用
20 changes: 20 additions & 0 deletions lib_fiber/samples/file_lock/stdafx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// stdafx.h : 标准系统包含文件的包含文件,
// 或是常用但不常更改的项目特定的包含文件
//

#pragma once


//#include <iostream>
//#include <tchar.h>

// TODO: 在此处引用程序要求的附加头文件

#include "lib_acl.h"
#include "fiber/libfiber.hpp"
#include "acl_cpp/lib_acl.hpp"

#ifdef WIN32
#define snprintf _snprintf
#endif

0 comments on commit 0e96092

Please sign in to comment.