Cannot use function cpuset_create from shared C library <cpuset.h> - c

I am trying to port a C project from a CentOS 7 (Core) to an Ubuntu 20.04.1 LTS (Focal Fossa) system. The program compiles and runs without problem on CentOS and also compiles without error on the Ubuntu system. However, when I try to execute the program on Ubuntu, I encounter the following error:
ERROR aff_prog_alloc #aff-executor.c:299 => cpuset_create: No such file or directory
The function cpuset_create is part of the <cpuset.h> library and the flag -lcpuset is included when compiling. The following is the output from the ldd command, showing the path for the <cpuset.h> library on our Ubuntu system:
$ ldd ./aff-executor
linux-vdso.so.1 (0x00007ffed97eb000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f8c179d5000)
libcpuset.so.1 => /lib/x86_64-linux-gnu/libcpuset.so.1 (0x00007f8c177c8000)
libbitmask.so.1 => /lib/x86_64-linux-gnu/libbitmask.so.1 (0x00007f8c175c4000)
libnuma.so.1 => /lib/x86_64-linux-gnu/libnuma.so.1 (0x00007f8c175b7000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f8c175ac000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8c173ba000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8c17a22000)
I verified that the library actually exists at this location:
$ll /lib/x86_64-linux-gnu/libcpuset.*
-rw-r--r-- 1 root root 67952 Nov 21 2016 /lib/x86_64-linux-gnu/libcpuset.a
lrwxrwxrwx 1 root root 18 Nov 21 2016 /lib/x86_64-linux-gnu/libcpuset.so -> libcpuset.so.1.1.0
lrwxrwxrwx 1 root root 18 Nov 21 2016 /lib/x86_64-linux-gnu/libcpuset.so.1 -> libcpuset.so.1.1.0
-rw-r--r-- 1 root root 52232 Nov 21 2016 /lib/x86_64-linux-gnu/libcpuset.so.1.1.0
Can anyone help with identifying why cpuset_create does not work on this system despite it having the correct syntax and inputs?
==================================
Update/Additional Info
The following code is what I need to use for my project. Everything works fine until the cpuset_create function which has been returning -1. I checked this program on a different Ubuntu (16.04.5 LTS (Xenial Xerus)) and it executed without problem on it, with cpuset_create returning the expected 0.
#define _GNU_SOURCE
#include<stdio.h>
#include <bitmask.h>
#include <cpuset.h>
#include <errno.h>
#include<numa.h>
typedef struct cpuset cpuset_t;
struct bitmask * get_mems_all(void);
/* return a bitmask describing all the available memory nodes */
struct bitmask * get_mems_all(void)
{
struct bitmask *ret;
if (numa_available() != -1){
printf("NUMA is available\n");
return numa_get_mems_allowed();
}
ret = bitmask_alloc(cpuset_mems_nbits());
printf("ret: %p\n",ret );
if (!ret)
printf("bitmask_alloc err");
bitmask_setbit(ret,0);
return ret;
}
int main(){
int err;
struct bitmask *mem_bm;
mem_bm=get_mems_all();
printf("mem_bm: %p\n",mem_bm );
numa_bitmask_clearbit(mem_bm, 1);
numa_bitmask_setbit(mem_bm,0);
char buff[256];
bitmask_displaylist(buff, sizeof(buff), mem_bm);
printf("buff: %s\n",buff );
printf("mem_bm: %p\n",mem_bm );
printf("cpuset lib version: %d\n",cpuset_version() );
cpuset_t *cpuset=cpuset_alloc();
printf("cpuset: %p\n",cpuset );
err = cpuset_setmems(cpuset,mem_bm);
printf("err cpuset_setmems: %d\n", err);
char* path="/AFF_1000/";
err = cpuset_create(path, cpuset);
printf("err cpuset_create: %d\n", err);
return 0;
}
Compilation:
gcc -Wall -O2 -std=gnu99 test.c -o test -lcpuset -lbitmask -lnuma
Output on Ubuntu 20.04.1 LTS (Focal Fossa):
$./test
NUMA is available
mem_bm: 0x55a34b2ac120
buff: 0
mem_bm: 0x55a34b2ac120
cpuset lib version: 3
cpuset: 0x55a34b2ac1d0
err cpuset_setmems: 0
err cpuset_create: -1
Expected output (this is from Ubuntu 16.04LTS (Xenial Xerus)):
$./test
NUMA is available
mem_bm: 0x1c39670
buff: 0
mem_bm: 0x1c39670
cpuset lib version: 3
cpuset: 0x1c396b0
err cpuset_setmems: 0
err cpuset_create: 0
$cset set -l
cset:
Name CPUs-X MEMs-X Tasks Subs Path
------------ ---------- - ------- - ----- ---- ----------
root 0-63 y 0-1 y 500 2 /
AFF_1000 ***** n 0 n 0 0 /AFF_1000
system 0-63 n 0 n 349 0 /system
However, I am unable to run the same program as root on Ubuntu 16.04 as well. I get the following error:
sudo ./test
./test: error while loading shared libraries: libcpuset.so.1: cannot open shared object file: No such file or directory
Does anyone know why this is happening? I do not know if this last problem is related to why my program won't run on the Ubuntu 20.04.

Related

Why does the return value -1 become 4294967295 when return type is int64_t?

In this code, I have a function whose return value is -1, but when assigned to int64_t type, the value obtained is 4294967295 instead of -1, but when assigned to int32_t type, it is -1. The return value of that zip_name_locate is of type int (4 bytes on my system). why is that?
#include <inttypes.h>
#include <stdio.h>
#include <zip.h>
int main() {
const char * path = "/home/www/api/default/current/public/static/doc/test.xlsx";
int error = ZIP_ER_NOENT;
zip_t* zip = zip_open(path, ZIP_RDONLY, &error);
int32_t n = zip_name_locate(zip, "xl/worksheets/_rels/sheet2.xml.rels", ZIP_FL_NODIR);
printf("%d\n", n);
int64_t j = zip_name_locate(zip, "xl/worksheets/_rels/sheet2.xml.rels", ZIP_FL_NODIR);
printf("%" PRId64 "\n", j);
return 0;
}
output:
-1
4294967295
This is my system information:
➜ ~ uname -r
3.10.0-1062.12.1.el7.x86_64
➜ ~ cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)
➜ ~ gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Thanks for answering, here are some answers to your questions:
About libzip, Because this is related to a bug I encountered in the process, so I need to use zip
My system is 64bit CentOS 7.7
zip_name_locate does return zip_int64_t type
I printed n and j in gdb, n is -1, j is 4196160, it seems that gdb cannot print integers of type int64_t, but this output indicates that j should not be -1
Because we used an old version of libzip in a certain environment and caused a bug, so we wanted to find the most fundamental reason, we used the built-in version 0.11
PRId64 is ld on my system
int64_t j = -1; and int64_t j = (int64_t)((zip_int64_t)-1); successful conversion
sizeof(long) is 8
I made a mistake. On my system, I have an old version of libzip and a new version of libzip, but when I tried to introduce the old version of libzip with the -L flag, the new version was actually introduced. The method I compiled is
gcc -L /usr/lib64 -lzip test1.c -o test and /usr/lib64 is where the old version of libzip dynamic shared library is located.
In my system, there are some libzip library files under /usr/lib64 and /usr/local/lib64, the old version under /usr/lib64, and the new version under /usr/local/lib64:
ls -lh /usr/local/lib64/libzip.so*
lrwxrwxrwx 1 root root 11 Jun 1 22:21 /usr/local/lib64/libzip.so -> libzip.so.5
lrwxrwxrwx 1 root root 13 Jun 1 22:21 /usr/local/lib64/libzip.so.5 -> libzip.so.5.3
-rwxr-xr-x 1 root root 162K Jun 1 23:18 /usr/local/lib64/libzip.so.5.3
ls -lh /usr/lib64/libzip.so*
-rwxr-xr-x 1 root root 57K Jun 2 00:02 /usr/lib64/libzip.so
lrwxrwxrwx 1 root root 11 Jun 2 00:07 /usr/lib64/libzip.so.2 -> libzip.so.5
-rwxr-xr-x 1 root root 57K Jun 2 00:02 /usr/lib64/libzip.so.2.1.0
-rwxr-xr-x 1 root root 57K Jun 2 00:02 /usr/lib64/libzip.so.5
I learned that the objdump command can check which shared libraries are dependent, so I checked it out and the following is the output:
objdump -p test | grep so
NEEDED libzip.so.2
NEEDED libc.so.6
required from libc.so.6:
Then I checked through ldconfig and found that libzip.so.2 points to the new version:
ldconfig -v | grep libzip
libzip.so.5 -> libzip.so.5.3
libzip.so.2 -> libzip.so.5
So in my question, it was based on a wrong judgment from the beginning, leading to incomprehensible imagination. If you are using a new version of libzip, the return value of zip_name_locate of libzip in the new version is zip_int64_t. This type is int64_t type on my system. When the 4294967295 return value of this type is assigned to int32_t, it causes overflow, so would be -1, and j would be 4294967295.

Cannot access EFS file programmatically with 32bits executable (on a 64bits OS)

I've got a problem accessing files programmatically on an Amazon EFS filesystem : the same C program will work with a 64 bits executable, but not with a 32bits executable.
Mount point is /EFS, the program below will list both EFS directory (/EFS/data) and local directory (/home/centos) :
Here is the test program :
#include <stdio.h>
#include <dirent.h>
int main(void) {
struct dirent *d;
char efs_dir[] = "/EFS/data";
char local_dir[] = "/home/centos";
printf("EFS dir : %s\n",efs_dir);
DIR *dirEFS = opendir(efs_dir);
if (dirEFS == NULL) {
printf("Could not open current directory");
return 1;
}
while ((d = readdir(dirEFS)) != NULL)
printf("%s\n", d->d_name);
closedir(dirEFS);
printf("\nlocal filesystem dir : %s\n",local_dir);
DIR *dirLOCAL = opendir(local_dir);
if (dirLOCAL == NULL) {
printf("Could not open current directory");
return 1;
}
while ((d = readdir(dirLOCAL)) != NULL)
printf("%s\n", d->d_name);
closedir(dirLOCAL);
return 0;
}
Unix view :
[centos#ec2-instance ~]$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/nvme0n1p1 20G 3.4G 16G 19% /
tmpfs 3.7G 0 3.7G 0% /dev/shm
/dev/nvme1n1p1 94G 6.1G 83G 7% /opt/data
fs-XXXXXXXX.eu-west-3.amazonaws.com:/
8.0E 5.3G 8.0E 1% /EFS
[centos#ec2-instance ~]$]$ ls -l /EFS/data
-rw-r--r-- 1 centos centos 2796 Sep 15 12:18 efs_file1.txt
-rw-r--r-- 1 centos centos 2812 Sep 15 12:18 efs_file2.txt
-rw-r--r-- 1 centos centos 3625 Sep 15 12:18 efs_file3.txt
-rw-r--r-- 1 centos centos 2768 Sep 15 12:18 efs_file4.txt
[centos#ec2-instance ~]$]$ ls -l /home/centos
-rw-rw-r-- 1 centos centos 2796 Sep 15 14:15 local_file1.txt
-rw-rw-r-- 1 centos centos 2812 Sep 15 14:15 local_file2.txt
-rw-rw-r-- 1 centos centos 3625 Sep 15 14:15 local_file3.txt
-rw-rw-r-- 1 centos centos 2768 Sep 15 14:15 local_file4.txt
-rw-r--r-- 1 centos centos 792 Sep 15 14:21 test_dir.c
-rwxrwxr-x 1 centos centos 7392 Sep 15 14:22 test_dir
When I compile test_dir.c in 32 bits compatibility mode, no results for the EFS directory :
[centos#ec2-instance ~]$ gcc test_dir.c -o test_dir -m32
[centos#ec2-instance ~]$ ./test_dir
EFS dir : /EFS/data
local filesystem dir : /home/centos
test_dir
.
..
local_file1.txt
local_file2.txt
local_file3.txt
local_file4.txt
test_dir.c
But for 64 bits executable it is fine :
[centos#ec2-instance ~]$ gcc test_dir.c -o test_dir
[centos#ec2-instance ~]$ ./test_dir
EFS dir : /EFS/data
.
..
efs_file1.txt
efs_file2.txt
efs_file3.txt
efs_file4.txt
local filesystem dir : /home/centos
test_dir
.
..
local_file1.txt
local_file2.txt
local_file3.txt
local_file4.txt
test_dir.c
Anyone has an idea of what is happening here ?
Thanks.
edit (solution) : compress the 64 bits inodes number to 32 bits with the kernel option nfs.enable_ino64=0
[root#eai ~]# cat /etc/modprobe.d/nfs.conf
options nfs enable_ino64=0
[root#eai ~]# reboot
and it's done ! Thanks DNT.
Function readdir returns an inode. In your 32bit build it expects to find 32bit inodes. But with a file system with 64bit inodes it will fail if the particular inode number cannot be expressed in 32bits.
To see the inode numbers you may want to use ls -li /EFS/data/efs_file1.txt. The leftmost number is the inode number and if it exceeds 4294967295 then it is 64bit and 32bit readdir cannot handle it.

Why can't I read /proc/pid/mem when I have read permission?

I would like to read the content of the memory file associated to one of my process (with PID 2614). I started to write a very small C program to check I can open it:
#include <stdio.h>
#include <errno.h>
int main() {
FILE* f = fopen("/proc/2614/mem", "rb");
if(!f) {
printf("Error %d\n", errno);
return -1;
}
fclose(f);
return 0;
}
When I run it I get a permission denied error:
$ gcc -o read read.c && ./read
Error 13
However, I have read permission:
$ whoami
pierre
$ ll /proc/2614/mem
-rw------- 1 pierre pierre 0 août 18 19:44 /proc/2614/mem
What's going on?
I know it is possible to read the file because I am able to do it on another system (and some other SO answers already did that). Here is information about my system:
$ uname -a
Linux pierre-computer 4.15.0-112-generic #113~16.04.1-Ubuntu SMP Fri Jul 10 04:37:08 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
And the information for the system on which I can read it:
$ uname -a
Linux not-pierre-computer 3.2.0-4-686-pae #1 SMP Debian 3.2.89-2 i686 GNU/Linux
Are there restrictions on some systems?

Compiling against gpsd on OpenWRT - linking fails

I'm trying to compile a tool that uses gps.h, but my compilation seems to fail each time when it tries to link to libgps. The error message I receive is:
/opt/openwrt-sdk/staging_dir/toolchain-arm_cortex-a9+vfpv3_gcc-7.3.0_musl_eabi/bin/../lib/gcc/arm-openwrt-linux-muslgnueabi/7.3.0/../../../../arm-openwrt-linux-muslgnueabi/bin/ld: cannot find -lgps
This is the command I'm compiling with:
arm-openwrt-linux-gcc -o ./bin/eagle src/main.c -I./src -I/opt/openwrt-sdk/staging_dir/target-arm_cortex-a9+vfpv3_musl_eabi/usr/include -static -L/opt/openwrt-sdk/staging_dir/target-arm_cortex-a9+vfpv3_musl_eabi/usr/lib -lpthread -lgps
Basic code for reference:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gps.h>
int main(void)
{
int rc;
struct gps_data_t gps_data;
if ((rc = gps_open("localhost", "2947", &gps_data)) == -1)
{
printf("code: %d, reason: %s\n", rc, gps_errstr(rc));
return 1;
}
gps_stream(&gps_data, WATCH_ENABLE | WATCH_JSON, NULL);
return 0;
}
And some directory listings in my toolchain - as far as I can tell, libgps has compiled successfully:
# ls -lah /opt/openwrt-sdk/staging_dir/target-arm_cortex-a9+vfpv3_musl_eabi/usr/include/ | grep gps
-rw-rw-r-- 1 root root 80K Sep 7 2017 gps.h
# ls -lah /opt/openwrt-sdk/staging_dir/target-arm_cortex-a9+vfpv3_musl_eabi/usr/lib/ | grep gps
lrwxrwxrwx 1 root root 16 Oct 17 18:46 libgps.so -> libgps.so.23.0.0
lrwxrwxrwx 1 root root 16 Oct 17 18:46 libgps.so.23 -> libgps.so.23.0.0
-rwxr-xr-x 1 root root 101K Oct 17 18:46 libgps.so.23.0.0
Many thanks in advance for any help.
Your link command line contains '-static', which prevents linking against *.so shared libraries (aka shared objects, hence 'so'), but still permits linking against *.a static-link libraries (aka archives).
See: https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
In the directory whose contents you listed, and which the link command line is directed towards using the '-L' flag, there is a shared object libgps.so, but there is no static-link library libgps.a .
This leaves the linker no way to satisfy the link-time dependency on libgps. The only way to satisfy it, using libgps.so, has been disabled using '-static'.
To fix, either:
Modify the tool's compile recipe, so as to remove '-static' from the link command line, so as to enable use of the shared object, or
Modify gpsd's compile recipe, so as to cause a static-link library libgps.a to built, either in addition to or instead of libgps.so.

how to use settimeofday(2)?

What am I doing wrong here? I expect settimeofday() to change the system time, not return EINVAL.
$ uname -a
Linux io 4.3.5-300.fc23.x86_64 #1 SMP Mon Feb 1 03:18:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
$ cat settimeofday.c
#include <sys/time.h>
#include <stdio.h>
int main()
{
struct timeval tv = {0, 0};
if (settimeofday(&tv, 0) == -1)
perror("settimeofday");
}
$ gcc settimeofday.c
$ sudo ./a.out
settimeofday: Invalid argument
The error is coming from a Thinkpad T450 running Fedora 23. The same code runs fine on OS X.
EDIT
To clarify, the command is being executed as root:
# whoami
root
# sudo ./a.out
settimeofday: Invalid argument
As expected, I get EPERM not EINVAL if I run the program as a regular user:
$ ./a.out
settimeofday: Operation not permitted
Commit e1d7ba was introduced to the Linux kernel in mid-2015 and restricts the value of the tv_sec field. The restriction is influenced by system uptime -- see the commit message and related LKML discussion for details.
That's what was causing the settimeofday call to return EINVAL and explains why the code runs on OS X and older Linux machines.
As shown in the manpage of settimeofday().
If either tv or tz is NULL, the corresponding structure is not set or returned.

Resources