Hi All

I'm a C++ noob so please don't be too harsh. I have written a tiny server using sockets. It forks children off for each connection. Trouble is I need have each child report back to the parent. I have been trying to set up a shared file using mmap (I'm not married to this idea though).

Problem I'm having is that the map->push_back(myRequestLog); fails without any error or any feedback.

If anyone can give me some pointers I would appreciate it.

int writeSharedMemory(RequestLog myRequestLog){
    int i;
    int fd;
    int result;
	bool existed = true;
    vector<RequestLog> *map;  /* mmapped array of RequestLog's */

	 /* Open a file for writing. */
    fd = open(FILEPATH, O_RDWR, (mode_t)0600);
    if (fd == -1) {
		existed = false;
		fd = open(FILEPATH, O_RDWR | O_CREAT, (mode_t)0600);
		if (fd == -1) {
			perror("Error opening file for writing");
			exit(EXIT_FAILURE);
		}
    }
	
	if(!existed){
		/* Stretch the file size to the size of the (mmapped) vector*/
		result = lseek(fd, FILESIZE-1, SEEK_SET);
		if (result == -1) {
			close(fd);
			perror("Error calling lseek() to 'stretch' the file");
			exit(EXIT_FAILURE);
		}

		result = write(fd, "", 1);
		if (result != 1) {
			close(fd);
			perror("Error writing last byte of the file");
			exit(EXIT_FAILURE);
		}
	}

    /* Now the file is ready to be mmapped.*/
	map = (vector<RequestLog>*)mmap(0, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED) {
		close(fd);
		perror("Error mmapping the file");
		exit(EXIT_FAILURE);
    }
	
    /* Now write int's to the file as if it were memory*/
	try{
		map->push_back(myRequestLog);
	} catch (const Error &error) {
		cout << error.get_msg() << "\n";
	}

    /* Don't forget to free the mmapped memory*/
    if (munmap(map, FILESIZE) == -1) {
		perror("Error un-mmapping the file");
		/* Decide here whether to close(fd) and exit() or not. Depends... */
    }

    /* Un-mmaping doesn't close the file, so we still need to do that.*/
    close(fd);
    return 0;
}

The line vector<RequestLog> *map; creates a pointer to a vector. Since it is a pointer, no vector yet exists, and any attempt to use it ( map->push_back( foo ); ) will fail.

I think what you want is a (vector of (pointer to RequestLog)), which is written: vector<RequestLog*> map; So your code should look something like this:

RequestLog *aMapping;
  vector<RequestLog*> mappings;

  ...

  aMapping = (RequestLog*)mmap(0, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  ...
  mappings.push_back( aMapping );

  ...

You must be very careful to watch what type of thing you are manipulating.

Now, if I misunderstood what you are trying to do:

I don't know if you can properly mmap a vector. Vectors work by allocating and deallocating from the program's heap, which is not shared between processes. You can subclass a new vector type that allocates and deallocates from a specific mmapping, but that will require a little bit of work...

Let us know what you are trying to do...

Thanks for that, I am probably going about it the wrong way. Basically I have a struct

struct RequestLog{
	string eventTime;
	string duration;
	string url;
	string client_ip;
	string thread_id;
	string status;
};

Every time a connection is made to the server, a process forks and deals with the request.

if (!fork()) { // this is the child process
			//get data from connection
			HandleHTTPRequest(sockfd);
            exit(0);
        }

I need a way in which the child process can fill in the above struct or something similar and add it to a list of some sort (anything that works is fine) so that the parent can see it and list all the reports fed back from each process.

Excellent. Then the code I gave you is correct.

Have fun.

Thanks for all your help Duoas. but ....

I'm still stuck. Just to be clear. Each process forks then completes and ends. Before it ends I need it to write it's RequestLog to a List held in memory. You are right Vectors will not work, they cause heap dumps. Your example would mean that I could only store 1 processes' RequestLog (If I'm not being daft). I just can't seem to find a way of storing ALL the forked processes RequestLogs in memory.

When requested, the parent could then display the results of every forked process that has run.

Thanks for patience and being kind enough to assist a noob!

The parent is the only process that needs to keep a list. Each child needs to worry about only one RequestLog.

The call to mmap() is the same, but what you do with the result is different: the parent stores the result in a vector, while the child just saves it in a single variable and writes and closes its end before terminating.

Hope this makes sense.

So if my parent is generating say 5 -10 forked children every second, each one modifying the mmap shared file - how does the parent get notified that it must add a new Requestlog to it's Vector before the mmap file is changed again by another child.

Ideally I would like the mmap file just to store all the RequestLog entries until it has reached a preset filesize or until the program exits.

Ah, I misunderstood.

Just mmap the file, then every time you fork() the child should inherit the handle to the mmapped file.

Each child should append to the file. The parent needs only seek to EOF and check the file position to see if something has happened.

I've got to ask though, why so many processes forking each second? You'll overload your processor.

Thanks i'll give that a go. It's tough this c++ stuff, Java gives it all to you for nothing ;-)

The forking is because its a server delivering XML to clients. I'll probably change it to a thread pool with pthreads once I've got my head around the basics.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.