[Gambas-bugtracker] Bug #2540: Gambas does not seem to be writing to same shared memory as local processes

bugtracker at gambaswiki.org bugtracker at gambaswiki.org
Wed May 4 03:14:09 CEST 2022


http://gambaswiki.org/bugtracker/edit?object=BUG.2540&from=L21haW4-

Gary SPRANG reported a new bug.

Summary
-------

Gambas does not seem to be writing to same shared memory as local processes

Type             : Bug
Priority         : Medium
Gambas version   : 3.16
Product          : Development Environment


Description
-----------

Process #1, the one that creates the shared memory segment:
	int shm_size=1048576;  /* was 524288 */
	char shm_id[] = {"/SHM_SEG"};
	int shm_fd; /* descriptor for shared memory */
	void *shm_addr;

	shm_fd = shm_open(shm_id, O_CREAT | O_RDWR, 0660);
	if (shm_fd == -1)
	{
		perror("Scanner: open");
		exit(-10);
	}
	/* set the shared memory length.  this is necessary, because it defaults to zero! */
	ftruncate(shm_fd, shm_size);
	/* map shared memory to process address space */
 	shm_addr = mmap(NULL, shm_size, PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0);
	if (shm_addr == MAP_FAILED)
	{
		perror("Scanner: mmap");
		exit(-30);
	}
	shmaddr2 = (char *)shm_addr; /* tie into existing pointer */
..................................................................................
The second process is the Logger module, which accepts messages from the other modules via queues,
and makes entries in the system log.  It connects successfully to the shared memory segment:
	int shm_size=1048576; /* was 524288 */
	char shm_id[] = {"/SHM_SEG"};
	int shm_fd; /* descriptor for shared memory */
	void *shm_addr;

	shm_fd = shm_open(shm_id, O_RDWR, 0660);
	if (shm_fd == -1)
	{
		perror("open");
		exit(-10);
	}
	/* map shared memory to process address space */
	/* void * mmap (void *address, size_t length, int protect, int flags, int filedes, off_t offset) */
 	shm_addr = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
	if (shm_addr == MAP_FAILED)
	{
		perror("mmap");
		exit(-30);
	}
	lshmaddr = (char *)shm_addr; /* tie into existing pointer */
.................................................................................
The "scanner" process forks, and starts the "logger".  Both processes write a heartbeat to shared memory, among other things.
Now in Gambas, in the Public Sub Form_Open() module...
  Dim uidptr As Pointer
  Dim protection As Integer
  Dim visibility As Integer 
  Dim buf1 As String
  Dim shm_size As Integer = 1048576
  Dim shm_fd As Integer
  Dim shm_addr As Pointer
  Dim shm_id As String = "/SHM_SEG"
  Dim vptr As Pointer = Null
  Dim mmap_err As Long

  protection = 3 ' PROT_READ | PROT_WRITE  MAP_FIXED = 16
  visibility = 2 ' MAP_SHARED(4) MAP_PRIVATE(2) 

shm_fd = shm_open(shm_id, 2, 666) ' 2=read/write 
  If shm_fd == -1 Then 
      Message.Info("shm_open() failed!", " OK ")
      Quit 
  Endif 
 ' map shared Memory To process address space
 shm_addr = mmap(0, shm_size, protection, visibility, shm_fd, 0)
 mmap_err = shm_addr ' convert the pointer to a long
 If mmap_err < 1 Then 
     Message.Info("mmap() failed!", " OK ")
     Quit
  Endif
  shmaddr2 = shm_addr
............................................................
Okay.  The first odd thing is, if I set the visibility flag for mmap() to MAP_SHARED, it will error out every time.
If I make the visibility MAP_PRIVATE, now Gambas can see the changing heartbeats from the two local processes, but
when Gambas writes to shared memory, Gambas can see the data, but neither of the local processes sees it.
The shared memory file has the appropriate permissions for both processes, and Gambas, to access it. 
Now, in Gambas, I am preserving the shared memory base address by copying it to another pointer, before I add offsets
to it.  Thus, I am using @byte, or @Integer to read from shared memory.
To shut down the system, Gambas has a pushbutton, which causes a write to shared memory + 66 of the character "Q".  Each
process watches this shared memory location, waiting for a command.
Public Sub btn_killsys_Click()

  Dim a As Integer
  Dim shmaddr5 As Pointer
  Dim SPstream As Stream
  shmaddr5 = global.shmaddr
  SPstream = Memory shmaddr5 For Write
      
  Message.title = "Shut Down SPOCS"
  a = message.Question("Are You Sure?", "YES", "NO")
  If a = 1 Then ' yes
    Seek #SPstream, +66
    Write #SPstream, "Q" ' remember that the stream pointer gets incremented
    Message.Info("SPOCS is Shutting Down!", "OK")
  Endif
  If a = 2 Then ' no
      'do nothing
  Endif
  End
This was the old method, from when I used shmat() to get shared memory.  I tried the memory pointer-and-memcpy()
method, but Gambas doesn't see the data.  On startup, the "scanner" loads a batch of data from a setup file into shared memory,
and  Gambas can see all of that.  But when Gambas writes, Gambas sees the data, but the local processes do not.
Any idea on what I am doing incorrectly?  Thanks!


System information
------------------

Gambas 3.16.2, Fedora Linux version 35, quad core AMD processor




More information about the Bugtracker mailing list