second shm_open() fails with ENOENT - linux

mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
shm_fd = shm_open("/ipc_shm", O_CREAT | O_RDWR, mode);
This works, returns 4 for shm_fd. The same process then calls a library function that also calls
fd = shm_open("/ipc_shm", O_RDWR, 0);
This one fails with errno set to 2, i.e. ENOENT (No such file or directory). There is no shm_unlink call in the middle. Any idea why the second call is failing. Appreciate your help.

my test.c:
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
int main (int argc, char *argv[])
{
mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
int shm_fd = shm_open("/ipc_shm", O_CREAT | O_RDWR, mode);
int fd = shm_open("/ipc_shm", O_RDWR, 0);
return 0;
}
compiled with gcc test.c -Wall -lrt works as expected:
$strace ./a.out
....
statfs("/dev/shm/", {f_type=0x1021994, f_bsize=4096, f_blocks=22290, f_bfree=22290, f_bavail=22290, f_files=55725, f_ffree=55723, f_fsid={0, 0}, f_namelen=255, f_frsize=4096}) = 0
futex(0xb6f5d1c0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
open("/dev/shm/ipc_shm", O_RDWR|O_CREAT|O_NOFOLLOW|O_CLOEXEC, 0777) = 3
fcntl64(3, F_GETFD) = 0x1 (flags FD_CLOEXEC)
open("/dev/shm/ipc_shm", O_RDWR|O_NOFOLLOW|O_CLOEXEC) = 4
exit_group(0)
Please run strace on your application, and search for all occurrences of ipc, and maybe chroot(). Maybe something unlinks the file?

Related

Will fallocate on mmap file reduce the memory consumption?

I am trying to mmap a 64M file into memory, then read & write into it. But sometimes a certain range within this file will no longer be used, so I called fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 16 << 20, 16 << 20); to release a 16M range inside it.
However, I find that the memory consumption seems not changed(both from free -m and from cat /proc/meminfo).
I understand that fallocate will dig some holes inside the file and return such range back to the filesystem. But I'm not sure whether it will reduce memory consumption for mmaped files.
If it does not reduce the memory consumption, where does such range go? Can another process get the underlying memory previously allocated to it?
The big.file is a normal 64M file instead of a sparse file
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <linux/falloc.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
uint8_t *addr;
int fd = open("home/big.file", O_RDWR | O_CREAT, 0777);
if (fd < 0)
return -1;
addr = (uint8_t *)mmap(NULL, MMAP_SIZE , PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (addr < 0)
return -1;
printf("data[0x%x] = %d\n", offset, addr[offset]);
getchar();
fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 16 << 20, 16 << 20);
getchar();
close(fd);
return 0;
}

mknod() not creating named pipe

I'm trying to create a FIFO named pipe using the mknod() command:
int main() {
char* file="pipe.txt";
int state;
state = mknod(file, S_IFIFO & 0777, 0);
printf("%d",state);
return 0;
}
But the file is not created in my current directory. I tried listing it by ls -l . State returns -1.
I found similar questions here and on other sites and I've tried the solution that most suggested:
int main() {
char* file="pipe.txt";
int state;
unlink(file);
state = mknod(file, S_IFIFO & 0777, 0);
printf("%d",state);
return 0;
}
This made no difference though and the error remains. Am I doing something wrong here or is there some sort of system intervention which is causing this problem?
Help.. Thanks in advance
You are using & to set the file type instead of |. From the docs:
The file type for path is OR'ed into the mode argument, and the
application shall select one of the following symbolic
constants...
Try this:
state = mknod(file, S_IFIFO | 0777, 0);
Because this works:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
char* file="pipe.txt";
int state;
unlink(file);
state = mknod(file, S_IFIFO | 0777, 0);
printf("state %d\n", state);
return 0;
}
Compile it:
gcc -o fifo fifo.c
Run it:
$ strace -e trace=mknod ./fifo
mknod("pipe.txt", S_IFIFO|0777) = 0
state 0
+++ exited with 0 +++
See the result:
$ ls -l pipe.txt
prwxrwxr-x. 1 lars lars 0 Jul 16 12:54 pipe.txt

My strace program gave wrong output under 64bit linux system

I am building an online judge system. The key point is to trace system calls.
I choose ptrace. The subprocess will stopped because of SIGTRAP when it's going to enter one system call, then the parent process goes to read the orig_rax (orig_eax)register of subprocess to get the system call number.
When the code is running under Opensuse13.1 32bit, no problem, its output is the same as the linux command strace.
But I just test the code under Opensuse13.1 64bit, Ubuntu12.04 64bit, its output is wrong.
The demo code can be downloaded here : https://gist.github.com/kainwen/41a7bd0198099d766bda
Under 64bit linux system, you save the code strace_ls.c, compile it gcc strace_ls.c, and run it./a.out 2>out. The output is here
So my code's output is strange.
My code and its output is below:
#include <sys/resource.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/user.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
void judge_exe()
{
pid_t pid ;
int insyscall = 0 ;
struct user context ;
pid = fork() ;
if (pid == 0) { //child
ptrace(PTRACE_TRACEME,0,NULL,NULL) ;
execl("/usr/bin/ls","ls",NULL) ;
}
else {//parent
int status ;
ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
while (1) {
wait(&status) ;
if (WIFEXITED(status)) //normally terminated
break;
else if (WIFSTOPPED(status) && (WSTOPSIG(status)==SIGTRAP)) {
if (!insyscall) {
insyscall = 1;
ptrace(PTRACE_GETREGS,pid,NULL,&context.regs);
fprintf(stderr,"syscall num: %d \n",context.regs.orig_rax);
} else
insyscall = 0;
}
ptrace(PTRACE_SYSCALL,pid,NULL,NULL);
}
return;
}
}
int main(int argc, char *argv[]) {
judge_exe();
}
The output of the code above is (just heading lines):
syscall num: 59
syscall num: 12
syscall num: 9
syscall num: 21
syscall num: 2
syscall num: 4
The heading lines of output of the linux command strace ls is:
execve("/usr/bin/ls", ["ls"], [/* 101 vars */]) = 0
brk(0) = 0x1bab000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efff4326000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/usr/lib64/mpi/gcc/openmpi/lib64/tls/x86_64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib64/mpi/gcc/openmpi/lib64/tls/x86_64", 0x7fff00c49b80) = -1 ENOENT (No such file or directory)
The number of system call sys_execve is 11, not 59 (the output of my code)
Solved
My method is right. The syscall number is different under 64bit and 32bit.

linux file attributes

Use open syscall to write and create a file ,there's no attributes with the file. fedora16 gcc-4.6.3
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
char * str= "helloworld";
int fd = open("test.db",O_WRONLY|O_CREAT|O_TRUNC|O_APPEND);
write(fd,str,10);
close(fd);
return 0;
}
ll test.db
----------. 1 jiamo jiamo 14 Apr 17 11:34 test.db
While it don't create file with the default file attributes such like touch test.db
umask : 0002
if drop the O_TRUNC
int fd = open("test1.db",O_WRONLY|O_CREAT|O_APPEND)
the file attributs is :
----rwx---. 1 jiamo jiamo 14 Apr 17 12:29 test1.db
Add the required permissions to the open() syscall:
int fd = open("test.db",O_WRONLY|O_CREAT|O_TRUNC|O_APPEND, 0666);
From the documentation:
mode must be specified when O_CREAT is in the flags, and is ignored otherwise.
The argument mode specifies the permissions to use in case a new file is created.
You need to pass the mode to open. Then it will set the permissions too. open is a variable argument function and you can pass more arguments to it
int open(const char *path, int oflag, ... );
Do something like
open(LOCKFILE, O_WRONLY | O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Check the various permission bits here

segfault on write() with ~8MB buffer (OSX, Linux)

I was curious what kind of buffer sizes write() and read() could handle on Linux/OSX/FreeBSD, so I started playing around with dumb programs like the following:
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
int main( void ) {
size_t s = 8*1024*1024 - 16*1024;
while( 1 ) {
s += 1024;
int f = open( "test.txt", O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR );
char mem[s];
size_t written = write( f, &mem[0], s );
close( f );
printf( "(%ld) %lu\n", sizeof(size_t), written );
}
return 0;
}
This allowed me to test how close to a seeming "8MB barrier" I could get before segfaulting. Somewhere around the 8MB mark, my program dies, here's an example output:
(8) 8373248
(8) 8374272
(8) 8375296
(8) 8376320
(8) 8377344
(8) 8378368
(8) 8379392
(8) 8380416
(8) 8381440
(8) 8382464
Segmentation fault: 11
This is the same on OSX and Linux, however my FreeBSD VM is not only much faster at running this test, it also can go on for quite a ways! I've successfully tested it up to 511MB, which is just a ridiculous amount of data to write in one call.
What is it that makes the write() call segfault, and how can I figure out the maximum amount that I can possibly write() in a single call, without doing something ridiculous like I'm doing right now?
(Note, all three operating systems are 64-bit, OSX 10.7.3, Ubuntu 11.10, FreeBSD 9.0)
The fault isn't within write(), it's a stack overflow. Try this:
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
int main( void )
{
void *mem;
size_t s = 512*1024*1024 - 16*1024;
while( 1 )
{
s += 1024;
int f = open( "test.txt", O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR );
mem = malloc(s);
size_t written = write( f, mem, s );
free(mem);
close( f );
printf( "(%ld) %lu\n", sizeof(size_t), written );
}
return 0;
}

Resources