- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在使用 C 语言编程,在内核为 2.6.18-238_xen_AMD64 的 RHEL5.6 上使用 berkeley db 4.3 (/usr/lib64/libdb-4.3.so)。
在我的测试中(写入 1,000,000 个键/值对),如果一个进程在数据库上的操作正在进行时异常退出(ctrl + c、kill 或断言失败),则以后对该数据库的操作将被阻止开幕。 Strace 显示进程在打开 __db.00x(例如 __db.001、__db.002、__db.003) 文件后卡在 futex(ptr_to_something, FUTEX_WAIT, 2, NULL) 调用处。
我知道清除锁定的唯一方法是删除 __db.00x 文件,以下测试表明数据库没有损坏。它满足了我的要求,但我只是想知道是否有更好(或更优雅)的方法来解决这个问题。
这里我列出了一些 strace stderr 和操作数据库的代码,这可能会有所帮助。
一些 strace stderr
...
open("__db.001", O_RDWR) = 3
fcntl(3, F_SETFD, FD_CLOEXEC) = 0
fstat(3, {st_mode=S_IFREG|0640, st_size=24576, ...}) = 0
close(3) = 0
open("__db.001", O_RDWR) = 3
fcntl(3, F_SETFD, FD_CLOEXEC) = 0
mmap(NULL, 24576, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0) = 0x2afcc4149000
close(3) = 0
futex(0x2afcc4149000, FUTEX_WAIT, 2, NULL **[[stuck here]]**
操作数据库的代码
typedef DB* db_handle;
db_handle bdb_open(const char *filename, u_int32_t cache_size_mb)
{
int ret;
DB_ENV *env;
db_handle dbp;
u_int32_t flags = DB_CREATE | DB_THREAD | DB_INIT_LOCK | DB_INIT_MPOOL | DB_INIT_LOCK ;
u_int32_t gb = cache_size_mb / 1024, mb = cache_size_mb % 1024;
if (ret = db_env_create(&env, 0)) {
fprintf(stderr, "db_env_create:%d, %s\n", ret, db_strerror(ret));
exit(EXIT_FAILURE);
}
if (ret = env->set_timeout(env, 3 * 1000000, DB_SET_LOCK_TIMEOUT)) {
fprintf(stderr, "env->set_timeout:%d, %s\n", ret, db_strerror(ret));
exit(EXIT_FAILURE);
}
if (ret = env->set_lk_detect(env, DB_LOCK_DEFAULT)) { /* this seems to be of no use in my case */
fprintf(stderr, "env->set_lk_detect:%d, %s\n", ret, db_strerror(ret));
exit(EXIT_FAILURE);
}
if (ret = env->set_cachesize(env, gb, mb * 1024 * 1024, 0)) {
fprintf(stderr, "env->set_cachesize:%d, %s\n", ret, db_strerror(ret));
exit(EXIT_FAILURE);
}
if ((ret = env->open(env, NULL, flags, 0)) != 0) {
fprintf(stderr, "db_env_open:%d, %s\n", ret, db_strerror(ret));
exit(EXIT_FAILURE);
}
if (ret = db_create(&dbp, env, 0)) {
fprintf(stderr, "db_create:%d, %s\n", ret, db_strerror(ret));
exit(EXIT_FAILURE);
}
if (ret = dbp->open(dbp, NULL, filename, NULL, DB_BTREE, flags, 0664)) {
fprintf(stderr, "dbp->open:%d, %s\n", ret, db_strerror(ret));
exit(EXIT_FAILURE);
}
return dbp;
}
int bdb_put(db_handle db, void* key, u_int32_t keylen, void* val, u_int32_t vallen)
{
DBT dkey, dval;
bzero(&dkey, sizeof(dkey));
bzero(&dval, sizeof(dval));
dkey.data = key, dkey.size = keylen;
dval.data = val, dval.size = vallen;
return db->put(db, NULL, &dkey, &dval, 0);
}
int bdb_get(db_handle db, void* key, const u_int32_t keylen,
void* buf, u_int32_t buflen, u_int32_t* nwrite)
{
DBT dkey, dval;
bzero(&dkey, sizeof(dkey));
bzero(&dval, sizeof(dval));
dkey.data = key, dkey.size = keylen;
dval.data = buf, dval.ulen = buflen, dval.flags = DB_DBT_USERMEM;
int ret = db->get(db, NULL, &dkey, &dval, 0);
if (ret == 0 && nwrite != NULL)
*nwrite = dval.size;
return ret;
}
最佳答案
__db* 文件包含锁的名称,但不包含锁本身。
pthread 锁是在内核 futexes 之上实现的。过程被杀死的那个可能在被杀死时有一个事件锁。
尝试运行“db_recover -h $DBHOME”来清除陈旧的锁。
还有一个可以添加的回调来自动化“陈旧锁”去除剂。
(旁白)您的代码几乎肯定需要处理 DB_RUNRECOVERY 和 DB_VERSION_MISMATCH来自 env->open 的错误代码用于稳健的实现。使用 DB_RECOVER 重新打开设置将处理。
在旧的 linux 上,也有可能出现“陈旧的 futex”(即一个 futex被死亡的进程锁定)只能被清除重新启动(还有另一种方法,使用“健壮的互斥锁”,设置允许另一个进程解锁先前锁定的互斥量的标志,但这并未在 Berkeley DB 中实现)。
关于linux - 伯克利数据库 : stuck at futex_wait because of previous abnormal quit during c api call,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12400663/
可以说我只是使用 pygame 有一个正常的游戏循环。 run = True while run: for event in pygame.event.get(): if ev
如何让控制台应用程序运行直到用户输入“Q”、“q”、“Quit”或“quit”来终止它? 这是我当前的代码: public class Class1 { [STAThread] static
我正在创建一个基于 promise 的 API。如果我一次发出一个请求,一切都会正常,但是,如果 2 个或更多请求在一秒内到达服务器,我会收到以下错误 Error: Cannot enqueue Qu
考虑: (gdb) q A debugging session is active. Inferior 1 [process 9018] will be killed. Quit an
我有以下设置: int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // Create the DBM
我的停靠菜单总是自动添加“退出”和其他 2 个菜单项,我如何阻止/修改它们? 更新: 确实没有办法删除/阻止/重定向“退出”菜单项。最后像打击一样使用了彼得的推荐希望对其他人有帮助 -(NSAppli
这是我的代码:1. 用户输入两个名称,中间有一个空格。这意味着需要读取两个字符串。 IE。输入: 约翰·多伊。 然后在字符数组中检查字符串。 (工作正常)。 while 循环一直持续到用户输入“sto
刚刚弄乱了 pygame 并遇到了这个错误。 代码: import sys import pygame pygame.init() size = width, height = 600, 400 sc
看完Eric Lippert’s answer我的印象是 await和 call/cc几乎是同一枚硬币的两面,最多只是句法上的差异。然而,在尝试实际实现时 call/cc在 C# 5 中,我遇到了一个
Memcached quit 命令用户关闭一个客户端连接 语法 quit 范例 连接到127.0.0.1 上 11211 的 Memcached 服务, 然后退出 $ telnet 12
这只是一种方便,但我认为很有用。请注意,IPython 和 Matlab 一样允许纯退出。因此,在 Julia 中允许混叠是合理的。 感谢您提供有关如何执行此操作的任何想法。 最佳答案 退出 Juli
我正在运行Django服务,该服务将启动chromedriver用于 Selenium ,并爬取网站以获取数据。 另一个Java服务通过HTTP调用Django服务。 这是代码: views.py p
Iam在我的游戏中一起使用Adcolony和Vungle时,一切正常,但是当用Application.Quit()游戏退出游戏时,关闭了游戏,但弹出了文本“不幸的应用程序崩溃”的弹出窗口。 在这里我附
我最近做了一个小游戏,然后用pyinstaller把它变成了一个应用程序。运行时,有两种关闭方式。它是全屏的,因此不包括单击红色 x 按钮,但基本上我有这个 if keys[pygame.K_ESCA
我正在练习使用递归,但有些东西我不太明白。例如,我写了这个简单的倒计时函数,它应该等到一秒过去,然后倒计时到下一秒。 我首先是这样写的: function countdown(sec) { con
我正在使用 Appium 安装应用程序。安装后,应用程序应该在后台运行。另一项测试应使用 Chrome 在应用程序在后台运行时检查互联网连接。问题是 driver.quit() 甚至启动 Androi
我有一个正在运行测试的框架;任何错误都会导致 WebDriver 实例调用类似 handleException 方法的方法,我在其中调用 driver.quit() 方法。我觉得 driver.qui
我知道所有基本的处理程序,即 on run、on open 和 onreopen。但是这个处理程序,on quit,让我很困惑。我的问题是,它的用途是什么以及它是如何触发的? 最佳答案 on quit
我有两个 for 循环: for event in pygame.event.get(): if event.type == QUIT:
我目前正在编写一个小的 GUI 程序,它可以完成一些工作并在之后退出。工作完成后,GUI 线程会更新用户的信息。 这是我目前使用的模式,我认为它不是最优雅的模式: static void MainFo
我是一名优秀的程序员,十分优秀!