views:

44

answers:

2

I apologize in advance for the long-winded question but I wanted to make sure I didn't leave out any key points that may alter your response.

I am responsible for maintaining system software written in 'C' of which we have a few common '.a' libraries. We have what I would call an "Execution Manager" who's main job is to fork and and exec a variable list of "test-job" executables and return control back to the Execution Manager once the test-job process terminates. All executables, including the execution manager, are statically linked against the aforementioned libraries. The execution manager and the test-job processes it forks use IPC via shared memory. One of the common libraries contains wrapper functions to create and attach the shared memory with a predefined key that never changes.

A few months ago we locked down our software (test-jobs plus execution manager), compiled them statically and released them to have the test-jobs "proofed". Since that time, there have been some requests for changes to be made to the execution manager which would require changes to a select few common library functions. However, management has decided that they do not want to recompile the test-jobs against the new version of the common libraries because that will require them to re-proof the test-job executables they currently have; and they do not want to expend the money to do that.

Since all executables were statically compiled, I would normally say mixing an Execution Manager with test-jobs statically compiled against different versions of the same common library would not be a problem. However, the inclusion of IPC via shared memory is making me wonder if that is still true. My gut says that as long as there were no changes to the shared memory wrapper functions, especially the key, then we should be OK, but I could really use some expert opinions on this.

Thanks for taking the time to read this, much appreciated.

+2  A: 

You should be OK, as long as the data structures and protocols that define how the processes talk to each other over the shared memory have not changed. (That is, your little ABI that exists between the two processes).

caf
This can be helped by adding a version field to the data stored in shm; an application can look for an existing value and exit with error if it can't handle the data structure version.
Ignacio Vazquez-Abrams
Thank you both for the reassurance and clarification on what things need to remain the same for this to work. I very much like the idea of a version field but it's sort of a catch 22 in that it's a bit too late to add. Perhaps there is an existing field with metadata that I can tack a version onto.Also, if you wouldn't mind could you take a look at my comment to BobS's post and let me know if my understanding is correct. Thanks again.
SiegeX
+1  A: 

I'd like to confirm what caf says. You have correctly identified the crucial bits: the key and the wrapper functions used to access the shared memory. These bits don't care whether they're defined in a .o file, whether they're part of a .a file, or where they are within a .a file. At link time, they get pulled into the exe, keeping their original functionality; their "temporary home" in a .a file doesn't affect how they find the shared memory segment, how they determine the relevant offsets, etc. So if these (i.e., the key and the wrapper functions) haven't changed, you should be set.

BobS
I should clarify that my main worry is that at compile/link time, the shared memory key translates to position 0x8000 in memory and if I were to recompile an executable *using the same shared memory wrapper functions (and therefore key)* that the shared memory position may change to location 0xABCD in memory causing all IPC to breakdown. However, it seems that the whole point in abstracting the allocated memory block to a key is to avoid this type of behavior and the actual mapping from key to logical memory position is handled by the OS making my worries unfounded. Does that sound correct?
SiegeX
The shared memory location isn't determined at compile and link time, unless you're asking for a specific location (eg. through the `shmaddr` parameter of `shmat()`, or the `addr` parameter of `mmap()` - in which case you can see in the source if that's been changed). If you're passing `NULL`, the OS decides at run time (and it's allowed to choose a different address for each run anyway).
caf
SiegeX: that seems correct to me (the latter part, of course). If it helps, consider that, for the non-shared-memory case, the memory location for int a may be different each time the process is run, since the executable may be loaded in a different memory location each time, even though the exe itself hasn't changed. Shared memory has (I assume) shielded you from that, so far, so you may infer that shared memory also protects you from the fact that your wrapper functions and key have moved around within the executable file.
BobS