0

I'm using a queue created with a circle buffer in C by mapping a file to two halves of the same underlying buffer, one after the other. If I attempt to access the buffer immediately after creating it (both before and after mapping the file on top), a bus error is thrown.

I'm programming on a x86 machine, so (if I understand correctly), the only reason this would occur is if the memory location is physically inaccessible. If this is the case, why would mmap return a physically unavailable address?

My code for creating a new code can be seen below.

struct queue create_queue() {
    size_t pagesize = getpagesize();
    size_t sz = ((BUFFSIZE*sizeof(char *))/pagesize)*(pagesize+1); //align to page
    int fd = fileno(tmpfile());
    
    void *buffer = mmap(NULL, 2*sz, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 
    mmap(buffer, sz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED, fd, 0); 
    mmap(buffer+sz, sz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED, fd, 0); 
        
    struct queue new_queue;
    
    new_queue.buffer = (char **)buffer;
    new_queue.front = 0;
    new_queue.back = 0;
    sem_init(&(new_queue.sem), 0, 0); 
    
    return new_queue;
}
muke
  • 306
  • 2
  • 11
  • 1
    `sizeof(char *)` Are you sure ? – wildplasser Jul 09 '20 at 23:59
  • 1
    You need to check the return value of `mmap`. You can't just assume the calls succeed. If any of them fail call `perror` for more detailed error description and then go from there. – kaylum Jul 09 '20 at 23:59
  • @wildplasser I want an array of pointers, so this should be correct no? – muke Jul 10 '20 at 00:02
  • @kaylum I've printf'ed the value of buffer and it is still a pointer. – muke Jul 10 '20 at 00:02
  • Yes, but you don't even store the return value of the last two `mmap` calls. That tells us you did not check those. Those can fail and checking `buffer` does not tell you that in any way. – kaylum Jul 10 '20 at 00:03
  • *"If MAP_FIXED is specified in flags, the system will try to place the mapping at the specified address, possibly removing a mapping that already exists at that location."* – user3386109 Jul 10 '20 at 00:04
  • As I said, the same behavior is observed before the second two `mmap` calls as well, so if they are failing it's an unrelated issue. – muke Jul 10 '20 at 00:04
  • @user3386109 this would be fine as it's mapping a file rather than creating a new anonymous mapping, and furthermore as I've said the behavior is observed even after just the first `mmap` call initializing `buffer`. – muke Jul 10 '20 at 00:05
  • @muke: yes, in that case it could be correct. – wildplasser Jul 10 '20 at 00:06
  • 1
    There's nothing in your code that actually accesses `buffer`. Where exactly does the bus error occur then? Is it in code not shown here? Do you have a back trace? Can you please show a [minimal verifiable example](https://stackoverflow.com/help/minimal-reproducible-example)? For the MVE, remove the other two `mmap` calls if you are saying they are not required to repro the problem. – kaylum Jul 10 '20 at 00:06
  • 2
    I think you need to post a [mcve]. – user3386109 Jul 10 '20 at 00:07
  • @kaylum I tested this with a memcpy which was just there for debugging purposes, if I insert `memcpy(buffer, "test", 4)` after `buffer` initialized though it causes a fault. – muke Jul 10 '20 at 00:09
  • 1
    It would save alot of time if you provide a minimal verifiable example from the beginning. It may even help you find the problem yourself in the process of constructing that example. Remove all the code and just have a single `main` that calls `mmap` with a fixed size and then access it. So essentially two lines of code. See if that repros the problem. Standard debugging step even if not preparing a post for SO. – kaylum Jul 10 '20 at 00:17

1 Answers1

0

The problem is that:

size_t sz = ((BUFFSIZE*sizeof(char *))/pagesize)*(pagesize+1); //align to page

does set sz to a multiple of the page size, but to a muiliple of the page size plus one. An alternative approach is:

size_t sz = ((BUFFSIZE*sizeof(char *)+pagesize-1)/pagesize)*pagesize; //align to page
Timothy Baldwin
  • 3,551
  • 1
  • 14
  • 23