在docker中使用flexlm管理license,大多数daemon都可以正常使用,但是针对新版本的synopsys的daemon确会出现报错,报错如下:
The daemon complains about not being able to open its lock file: /var/tmp/locksnpslmd, but /var/tmp
exists and is writable.
通过跟踪发现:
munmap(0x7fa322830000, 167936) = 0
setsid() = 64
openat(AT_FDCWD, "/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
getdents(3, /* 22 entries */, 32768) = 568
getdents(3, /* 0 entries */, 32768) = 0
close(3) = 0
write(1, "17:35:24 (snpslmd) Cannot open d"..., 4817:35:24 (snpslmd) Cannot open daemon lock file
) = 48
write(1, "17:35:24 (snpslmd) EXITING DUE T"..., 5817:35:24 (snpslmd) EXITING DUE TO SIGNAL 41 Exit reason 9
) = 58
exit_group(41) = ?
+++ exited with 41 +++**
解释原因如下:
发生这种情况是因为getdents()函数中“/”的“.”和“..”子目录返回不同的索引节点编号。可以使用snpslmd的LD_PRELOAD hack修复,保存一下内容为snpslmd-ld.c
#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <dirent.h> #include <dlfcn.h> #include <string.h> static int is_root = 0; static int d_ino = -1; static DIR *(*orig_opendir)(const char *name); static int (*orig_closedir)(DIR *dirp); static struct dirent *(*orig_readdir)(DIR *dirp); DIR *opendir(const char *name) { if (strcmp(name, "/") == 0) { is_root = 1; } return orig_opendir(name); } int closedir(DIR *dirp) { is_root = 0; return orig_closedir(dirp); } struct dirent *readdir(DIR *dirp) { struct dirent *r = orig_readdir(dirp); if (is_root && r) { if (strcmp(r->d_name, ".") == 0) { r->d_ino = d_ino; } else if (strcmp(r->d_name, "..") == 0) { r->d_ino = d_ino; } } return r; } static __attribute__((constructor)) void init_methods() { orig_opendir = dlsym(RTLD_NEXT, "opendir"); orig_closedir = dlsym(RTLD_NEXT, "closedir"); orig_readdir = dlsym(RTLD_NEXT, "readdir"); DIR *d = orig_opendir("/"); struct dirent *e = orig_readdir(d); while (e) { if (strcmp(e->d_name, ".") == 0) { d_ino = e->d_ino; break; } e = orig_readdir(d); } orig_closedir(d); if (d_ino == -1) { puts("Failed to determine root directory inode number"); exit(EXIT_FAILURE); } }
编译成so文件
gcc -ldl -shared -fPIC snpslmd-ld.c -o snpslmd-ld.so
使用如下方法:
#!/bin/sh export LD_PRELOAD=snpslmd-hack.so exec /usr/bin/snpslmd_bin "$@"
也可以在docker启动前加载:
docker run -it --privileged -d -e LD_PRELOAD="/root/snpdlmd-ld.so" xxxxx xxxx xxxx xxxx
网友留言: