Split ipc posix/systemv in different files

This commit is contained in:
Quentin Renard
2024-11-24 15:47:07 +01:00
parent bf9b3282fb
commit 9ecf65c78c
10 changed files with 505 additions and 497 deletions

View File

@@ -31,7 +31,9 @@ jobs:
run: go mod download
- name: Run tests
run: go test -race -covermode atomic -coverprofile=covprofile ./...
run: |
echo "CGO_ENABLED=0" >> $env:GITHUB_ENV
go test -race -covermode atomic -coverprofile=covprofile ./...
- if: github.event_name != 'pull_request'
name: Send coverage

27
ipc.h
View File

@@ -1,27 +0,0 @@
#include <sys/stat.h>
#include <sys/types.h>
/*
Posix
*/
int astikit_close(int fd, int *errno_ptr);
int astikit_fstat(int fd, struct stat *s, int *errno_ptr);
int astikit_ftruncate(int fd, off_t length, int *errno_ptr);
void *astikit_mmap(size_t length, int fd, int *errno_ptr);
int astikit_munmap(void *addr, size_t length, int *errno_ptr);
int astikit_shm_open(char *name, int flags, mode_t mode, int *errno_ptr);
int astikit_shm_unlink(char *name, int *errno_ptr);
/*
System V
*/
int astikit_ftok(char *path, int project_id, int *errno_ptr);
int astikit_sem_get(key_t key, int flags, int *errno_ptr);
int astikit_sem_close(int id, int *errno_ptr);
int astikit_sem_lock(int id, int *errno_ptr);
int astikit_sem_unlock(int id, int *errno_ptr);
void *astikit_shm_at(int id, int *errno_ptr);
int astikit_shm_get(key_t key, int size, int flags, int *errno_ptr);
int astikit_shm_close(int id, const void *addr, int *errno_ptr);

75
ipc_posix.c Normal file
View File

@@ -0,0 +1,75 @@
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
int astikit_close(int fd, int *errno_ptr)
{
int ret = close(fd);
if (ret < 0)
{
*errno_ptr = errno;
}
return ret;
}
int astikit_fstat(int fd, struct stat *s, int *errno_ptr)
{
int ret = fstat(fd, s);
if (ret < 0)
{
*errno_ptr = errno;
}
return ret;
}
int astikit_ftruncate(int fd, off_t length, int *errno_ptr)
{
int ret = ftruncate(fd, length);
if (ret < 0)
{
*errno_ptr = errno;
}
return ret;
}
void *astikit_mmap(size_t length, int fd, int *errno_ptr)
{
void *addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED)
{
*errno_ptr = errno;
return NULL;
}
return addr;
}
int astikit_munmap(void *addr, size_t length, int *errno_ptr)
{
int ret = munmap(addr, length);
if (ret < 0)
{
*errno_ptr = errno;
}
return ret;
}
int astikit_shm_open(char *name, int flags, mode_t mode, int *errno_ptr)
{
int fd = shm_open(name, flags, mode);
if (fd < 0)
{
*errno_ptr = errno;
}
return fd;
}
int astikit_shm_unlink(char *name, int *errno_ptr)
{
int ret = shm_unlink(name);
if (ret < 0)
{
*errno_ptr = errno;
}
return ret;
}

296
ipc_posix.go Normal file
View File

@@ -0,0 +1,296 @@
//go:build !windows
package astikit
//#include <stdlib.h>
//#include <string.h>
//#include "ipc_posix.h"
import "C"
import (
"errors"
"fmt"
"os"
"strconv"
"strings"
"sync"
"syscall"
"unsafe"
)
type PosixSharedMemory struct {
addr unsafe.Pointer
cname string
fd *C.int
name string
size int
unlink bool
}
func newPosixSharedMemory(name string, flags, mode int, cb func(shm *PosixSharedMemory) error) (shm *PosixSharedMemory, err error) {
// Create shared memory
shm = &PosixSharedMemory{name: name}
// To have a similar behavior with python, we need to handle the leading slash the same way:
// - make sure the "public" name has no leading "/"
// - make sure the "internal" name has a leading "/"
shm.name = strings.TrimPrefix(shm.name, "/")
shm.cname = "/" + shm.name
// Get c name
cname := C.CString(shm.cname)
defer C.free(unsafe.Pointer(cname))
// Get file descriptor
var errno C.int
fd := C.astikit_shm_open(cname, C.int(flags), C.mode_t(mode), &errno)
if fd < 0 {
err = fmt.Errorf("astikit: shm_open failed: %w", syscall.Errno(errno))
return
}
shm.fd = &fd
// Make sure to close shared memory in case of error
defer func() {
if err != nil {
shm.Close()
}
}()
// Callback
if cb != nil {
if err = cb(shm); err != nil {
err = fmt.Errorf("astikit: callback failed: %w", err)
return
}
}
// Get size
var stat C.struct_stat
if ret := C.astikit_fstat(*shm.fd, &stat, &errno); ret < 0 {
err = fmt.Errorf("astikit: fstat failed: %w", syscall.Errno(errno))
return
}
shm.size = int(stat.st_size)
// Map memory
addr := C.astikit_mmap(C.size_t(shm.size), *shm.fd, &errno)
if addr == nil {
err = fmt.Errorf("astikit: mmap failed: %w", syscall.Errno(errno))
return
}
// Update addr
shm.addr = addr
return
}
func CreatePosixSharedMemory(name string, size int) (*PosixSharedMemory, error) {
return newPosixSharedMemory(name, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0600, func(shm *PosixSharedMemory) (err error) {
// Shared memory needs to be unlink on close
shm.unlink = true
// Truncate
var errno C.int
if ret := C.astikit_ftruncate(*shm.fd, C.off_t(size), &errno); ret < 0 {
err = fmt.Errorf("astikit: ftruncate failed: %w", syscall.Errno(errno))
return
}
return
})
}
func OpenPosixSharedMemory(name string) (*PosixSharedMemory, error) {
return newPosixSharedMemory(name, os.O_RDWR, 0600, nil)
}
func (shm *PosixSharedMemory) Close() error {
// Unlink
if shm.unlink {
// Get c name
cname := C.CString(shm.cname)
defer C.free(unsafe.Pointer(cname))
// Unlink
var errno C.int
if ret := C.astikit_shm_unlink(cname, &errno); ret < 0 {
return fmt.Errorf("astikit: unlink failed: %w", syscall.Errno(errno))
}
shm.unlink = false
}
// Unmap memory
if shm.addr != nil {
var errno C.int
if ret := C.astikit_munmap(shm.addr, C.size_t(shm.size), &errno); ret < 0 {
return fmt.Errorf("astikit: munmap failed: %w", syscall.Errno(errno))
}
shm.addr = nil
}
// Close file descriptor
if shm.fd != nil {
var errno C.int
if ret := C.astikit_close(*shm.fd, &errno); ret < 0 {
return fmt.Errorf("astikit: close failed: %w", syscall.Errno(errno))
}
shm.fd = nil
}
return nil
}
func (shm *PosixSharedMemory) Write(src unsafe.Pointer, size int) error {
// Unmapped
if shm.addr == nil {
return errors.New("astikit: shared memory is unmapped")
}
// Copy
C.memcpy(shm.addr, src, C.size_t(size))
return nil
}
func (shm *PosixSharedMemory) WriteBytes(b []byte) error {
// Get c bytes
cb := C.CBytes(b)
defer C.free(cb)
// Write
return shm.Write(cb, len(b))
}
func (shm *PosixSharedMemory) ReadBytes(size int) ([]byte, error) {
// Unmapped
if shm.addr == nil {
return nil, errors.New("astikit: shared memory is unmapped")
}
// Get bytes
return C.GoBytes(shm.addr, C.int(size)), nil
}
func (shm *PosixSharedMemory) Name() string {
return shm.name
}
func (shm *PosixSharedMemory) Size() int {
return shm.size
}
func (shm *PosixSharedMemory) Addr() unsafe.Pointer {
return shm.addr
}
type PosixVariableSizeSharedMemoryWriter struct {
m sync.Mutex // Locks write operations
prefix string
shm *PosixSharedMemory
}
func NewPosixVariableSizeSharedMemoryWriter(prefix string) *PosixVariableSizeSharedMemoryWriter {
return &PosixVariableSizeSharedMemoryWriter{prefix: prefix}
}
func (w *PosixVariableSizeSharedMemoryWriter) closeSharedMemory() {
if w.shm != nil {
w.shm.Close()
}
}
func (w *PosixVariableSizeSharedMemoryWriter) Close() {
w.closeSharedMemory()
}
func (w *PosixVariableSizeSharedMemoryWriter) Write(src unsafe.Pointer, size int) (ro PosixVariableSizeSharedMemoryReadOptions, err error) {
// Lock
w.m.Lock()
defer w.m.Unlock()
// Shared memory has not yet been created or previous shared memory segment is too small
if w.shm == nil || size > w.shm.Size() {
// Close previous shared memory
w.closeSharedMemory()
// Create shared memory
var shm *PosixSharedMemory
if shm, err = CreatePosixSharedMemory(w.prefix+"-"+strconv.Itoa(size), size); err != nil {
err = fmt.Errorf("astikit: creating shared memory failed: %w", err)
return
}
// Store shared memory
w.shm = shm
}
// Write
if err = w.shm.Write(src, size); err != nil {
err = fmt.Errorf("astikit: writing to shared memory failed: %w", err)
return
}
// Create read options
ro = PosixVariableSizeSharedMemoryReadOptions{
Name: w.shm.Name(),
Size: size,
}
return
}
func (w *PosixVariableSizeSharedMemoryWriter) WriteBytes(b []byte) (PosixVariableSizeSharedMemoryReadOptions, error) {
// Get c bytes
cb := C.CBytes(b)
defer C.free(cb)
// Write
return w.Write(cb, len(b))
}
type PosixVariableSizeSharedMemoryReader struct {
m sync.Mutex // Locks read operations
shm *PosixSharedMemory
}
func NewPosixVariableSizeSharedMemoryReader() *PosixVariableSizeSharedMemoryReader {
return &PosixVariableSizeSharedMemoryReader{}
}
func (r *PosixVariableSizeSharedMemoryReader) closeSharedMemory() {
if r.shm != nil {
r.shm.Close()
}
}
func (r *PosixVariableSizeSharedMemoryReader) Close() {
r.closeSharedMemory()
}
type PosixVariableSizeSharedMemoryReadOptions struct {
Name string `json:"name"`
Size int `json:"size"`
}
func (r *PosixVariableSizeSharedMemoryReader) ReadBytes(o PosixVariableSizeSharedMemoryReadOptions) (b []byte, err error) {
// Lock
r.m.Lock()
defer r.m.Unlock()
// Shared memory has not yet been opened or shared memory's name has changed
if r.shm == nil || r.shm.Name() != o.Name {
// Close previous shared memory
r.closeSharedMemory()
// Open shared memory
var shm *PosixSharedMemory
if shm, err = OpenPosixSharedMemory(o.Name); err != nil {
err = fmt.Errorf("astikit: opening shared memory failed: %w", err)
return
}
// Store attributes
r.shm = shm
}
// Copy
b = make([]byte, o.Size)
C.memcpy(unsafe.Pointer(&b[0]), r.shm.Addr(), C.size_t(o.Size))
return
}

10
ipc_posix.h Normal file
View File

@@ -0,0 +1,10 @@
#include <sys/stat.h>
#include <sys/types.h>
int astikit_close(int fd, int *errno_ptr);
int astikit_fstat(int fd, struct stat *s, int *errno_ptr);
int astikit_ftruncate(int fd, off_t length, int *errno_ptr);
void *astikit_mmap(size_t length, int fd, int *errno_ptr);
int astikit_munmap(void *addr, size_t length, int *errno_ptr);
int astikit_shm_open(char *name, int flags, mode_t mode, int *errno_ptr);
int astikit_shm_unlink(char *name, int *errno_ptr);

110
ipc_posix_test.go Normal file
View File

@@ -0,0 +1,110 @@
//go:build !windows
package astikit
import (
"bytes"
"testing"
)
func TestPosixSharedMemory(t *testing.T) {
sm1, err := CreatePosixSharedMemory("/test", 8)
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
defer sm1.Close()
if sm1.Addr() == nil {
t.Fatal("expected not nil, got nil")
}
if g := sm1.Size(); g <= 0 {
t.Fatalf("expected > 0, got %d", g)
}
if e, g := "test", sm1.Name(); e != g {
t.Fatalf("expected %v, got %v", e, g)
}
if _, err = CreatePosixSharedMemory("/test", 8); err == nil {
t.Fatal("expected error, got nil")
}
b1 := []byte("test")
if err := sm1.WriteBytes(b1); err != nil {
t.Fatalf("expected no error, got %s", err)
}
sm2, err := OpenPosixSharedMemory("test")
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
defer sm2.Close()
b2, err := sm2.ReadBytes(len(b1))
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
if e, g := b1, b2; !bytes.Equal(b1, b2) {
t.Fatalf("expected %s, got %s", e, g)
}
if err = sm1.Close(); err != nil {
t.Fatalf("expected no error, got %s", err)
}
if err = sm1.WriteBytes(b1); err == nil {
t.Fatal("expected error, got nil")
}
if err = sm1.Close(); err != nil {
t.Fatalf("expected no error, got %s", err)
}
if err = sm2.Close(); err != nil {
t.Fatalf("expected no error, got %s", err)
}
if _, err = sm2.ReadBytes(len(b1)); err == nil {
t.Fatal("expected error, got nil")
}
if err = sm2.Close(); err != nil {
t.Fatalf("expected no error, got %s", err)
}
}
func TestPosixVariableSizeSharedMemory(t *testing.T) {
w := NewPosixVariableSizeSharedMemoryWriter("test-1")
defer w.Close()
r := NewPosixVariableSizeSharedMemoryReader()
defer r.Close()
b1 := []byte("test")
ro1, err := w.WriteBytes(b1)
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
if e, g := w.shm.Name(), ro1.Name; e != g {
t.Fatalf("expected %s, got %s", e, g)
}
if e, g := len(b1), ro1.Size; e != g {
t.Fatalf("expected %d, got %d", e, g)
}
b2, err := r.ReadBytes(ro1)
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
if !bytes.Equal(b1, b2) {
t.Fatalf("expected %s, got %s", b1, b2)
}
b3 := make([]byte, w.shm.Size()+1)
b3[0] = 'a'
b3[len(b3)-1] = 'b'
ro2, err := w.WriteBytes(b3)
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
if ro1.Name == ro2.Name {
t.Fatal("expected different, got equalt")
}
b4, err := r.ReadBytes(ro2)
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
if !bytes.Equal(b3, b4) {
t.Fatalf("expected %s, got %s", b3, b4)
}
}

View File

@@ -1,91 +1,7 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
/*
Posix
*/
int astikit_close(int fd, int *errno_ptr)
{
int ret = close(fd);
if (ret < 0)
{
*errno_ptr = errno;
}
return ret;
}
int astikit_fstat(int fd, struct stat *s, int *errno_ptr)
{
int ret = fstat(fd, s);
if (ret < 0)
{
*errno_ptr = errno;
}
return ret;
}
int astikit_ftruncate(int fd, off_t length, int *errno_ptr)
{
int ret = ftruncate(fd, length);
if (ret < 0)
{
*errno_ptr = errno;
}
return ret;
}
void *astikit_mmap(size_t length, int fd, int *errno_ptr)
{
void *addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED)
{
*errno_ptr = errno;
return NULL;
}
return addr;
}
int astikit_munmap(void *addr, size_t length, int *errno_ptr)
{
int ret = munmap(addr, length);
if (ret < 0)
{
*errno_ptr = errno;
}
return ret;
}
int astikit_shm_open(char *name, int flags, mode_t mode, int *errno_ptr)
{
int fd = shm_open(name, flags, mode);
if (fd < 0)
{
*errno_ptr = errno;
}
return fd;
}
int astikit_shm_unlink(char *name, int *errno_ptr)
{
int ret = shm_unlink(name);
if (ret < 0)
{
*errno_ptr = errno;
}
return ret;
}
/*
System V
*/
int astikit_ftok(char *path, int project_id, int *errno_ptr)
{

View File

@@ -3,301 +3,19 @@
package astikit
//#include <sys/shm.h>
//#include <sys/stat.h>
//#include <stdlib.h>
//#include <string.h>
//#include "ipc.h"
//#include "ipc_systemv.h"
import "C"
import (
"errors"
"fmt"
"os"
"strconv"
"strings"
"sync"
"syscall"
"time"
"unsafe"
)
type PosixSharedMemory struct {
addr unsafe.Pointer
cname string
fd *C.int
name string
size int
unlink bool
}
func newPosixSharedMemory(name string, flags, mode int, cb func(shm *PosixSharedMemory) error) (shm *PosixSharedMemory, err error) {
// Create shared memory
shm = &PosixSharedMemory{name: name}
// To have a similar behavior with python, we need to handle the leading slash the same way:
// - make sure the "public" name has no leading "/"
// - make sure the "internal" name has a leading "/"
shm.name = strings.TrimPrefix(shm.name, "/")
shm.cname = "/" + shm.name
// Get c name
cname := C.CString(shm.cname)
defer C.free(unsafe.Pointer(cname))
// Get file descriptor
var errno C.int
fd := C.astikit_shm_open(cname, C.int(flags), C.mode_t(mode), &errno)
if fd < 0 {
err = fmt.Errorf("astikit: shm_open failed: %w", syscall.Errno(errno))
return
}
shm.fd = &fd
// Make sure to close shared memory in case of error
defer func() {
if err != nil {
shm.Close()
}
}()
// Callback
if cb != nil {
if err = cb(shm); err != nil {
err = fmt.Errorf("astikit: callback failed: %w", err)
return
}
}
// Get size
var stat C.struct_stat
if ret := C.astikit_fstat(*shm.fd, &stat, &errno); ret < 0 {
err = fmt.Errorf("astikit: fstat failed: %w", syscall.Errno(errno))
return
}
shm.size = int(stat.st_size)
// Map memory
addr := C.astikit_mmap(C.size_t(shm.size), *shm.fd, &errno)
if addr == nil {
err = fmt.Errorf("astikit: mmap failed: %w", syscall.Errno(errno))
return
}
// Update addr
shm.addr = addr
return
}
func CreatePosixSharedMemory(name string, size int) (*PosixSharedMemory, error) {
return newPosixSharedMemory(name, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0600, func(shm *PosixSharedMemory) (err error) {
// Shared memory needs to be unlink on close
shm.unlink = true
// Truncate
var errno C.int
if ret := C.astikit_ftruncate(*shm.fd, C.off_t(size), &errno); ret < 0 {
err = fmt.Errorf("astikit: ftruncate failed: %w", syscall.Errno(errno))
return
}
return
})
}
func OpenPosixSharedMemory(name string) (*PosixSharedMemory, error) {
return newPosixSharedMemory(name, os.O_RDWR, 0600, nil)
}
func (shm *PosixSharedMemory) Close() error {
// Unlink
if shm.unlink {
// Get c name
cname := C.CString(shm.cname)
defer C.free(unsafe.Pointer(cname))
// Unlink
var errno C.int
if ret := C.astikit_shm_unlink(cname, &errno); ret < 0 {
return fmt.Errorf("astikit: unlink failed: %w", syscall.Errno(errno))
}
shm.unlink = false
}
// Unmap memory
if shm.addr != nil {
var errno C.int
if ret := C.astikit_munmap(shm.addr, C.size_t(shm.size), &errno); ret < 0 {
return fmt.Errorf("astikit: munmap failed: %w", syscall.Errno(errno))
}
shm.addr = nil
}
// Close file descriptor
if shm.fd != nil {
var errno C.int
if ret := C.astikit_close(*shm.fd, &errno); ret < 0 {
return fmt.Errorf("astikit: close failed: %w", syscall.Errno(errno))
}
shm.fd = nil
}
return nil
}
func (shm *PosixSharedMemory) Write(src unsafe.Pointer, size int) error {
// Unmapped
if shm.addr == nil {
return errors.New("astikit: shared memory is unmapped")
}
// Copy
C.memcpy(shm.addr, src, C.size_t(size))
return nil
}
func (shm *PosixSharedMemory) WriteBytes(b []byte) error {
// Get c bytes
cb := C.CBytes(b)
defer C.free(cb)
// Write
return shm.Write(cb, len(b))
}
func (shm *PosixSharedMemory) ReadBytes(size int) ([]byte, error) {
// Unmapped
if shm.addr == nil {
return nil, errors.New("astikit: shared memory is unmapped")
}
// Get bytes
return C.GoBytes(shm.addr, C.int(size)), nil
}
func (shm *PosixSharedMemory) Name() string {
return shm.name
}
func (shm *PosixSharedMemory) Size() int {
return shm.size
}
func (shm *PosixSharedMemory) Addr() unsafe.Pointer {
return shm.addr
}
type PosixVariableSizeSharedMemoryWriter struct {
m sync.Mutex // Locks write operations
prefix string
shm *PosixSharedMemory
}
func NewPosixVariableSizeSharedMemoryWriter(prefix string) *PosixVariableSizeSharedMemoryWriter {
return &PosixVariableSizeSharedMemoryWriter{prefix: prefix}
}
func (w *PosixVariableSizeSharedMemoryWriter) closeSharedMemory() {
if w.shm != nil {
w.shm.Close()
}
}
func (w *PosixVariableSizeSharedMemoryWriter) Close() {
w.closeSharedMemory()
}
func (w *PosixVariableSizeSharedMemoryWriter) Write(src unsafe.Pointer, size int) (ro PosixVariableSizeSharedMemoryReadOptions, err error) {
// Lock
w.m.Lock()
defer w.m.Unlock()
// Shared memory has not yet been created or previous shared memory segment is too small
if w.shm == nil || size > w.shm.Size() {
// Close previous shared memory
w.closeSharedMemory()
// Create shared memory
var shm *PosixSharedMemory
if shm, err = CreatePosixSharedMemory(w.prefix+"-"+strconv.Itoa(size), size); err != nil {
err = fmt.Errorf("astikit: creating shared memory failed: %w", err)
return
}
// Store shared memory
w.shm = shm
}
// Write
if err = w.shm.Write(src, size); err != nil {
err = fmt.Errorf("astikit: writing to shared memory failed: %w", err)
return
}
// Create read options
ro = PosixVariableSizeSharedMemoryReadOptions{
Name: w.shm.Name(),
Size: size,
}
return
}
func (w *PosixVariableSizeSharedMemoryWriter) WriteBytes(b []byte) (PosixVariableSizeSharedMemoryReadOptions, error) {
// Get c bytes
cb := C.CBytes(b)
defer C.free(cb)
// Write
return w.Write(cb, len(b))
}
type PosixVariableSizeSharedMemoryReader struct {
m sync.Mutex // Locks read operations
shm *PosixSharedMemory
}
func NewPosixVariableSizeSharedMemoryReader() *PosixVariableSizeSharedMemoryReader {
return &PosixVariableSizeSharedMemoryReader{}
}
func (r *PosixVariableSizeSharedMemoryReader) closeSharedMemory() {
if r.shm != nil {
r.shm.Close()
}
}
func (r *PosixVariableSizeSharedMemoryReader) Close() {
r.closeSharedMemory()
}
type PosixVariableSizeSharedMemoryReadOptions struct {
Name string `json:"name"`
Size int `json:"size"`
}
func (r *PosixVariableSizeSharedMemoryReader) ReadBytes(o PosixVariableSizeSharedMemoryReadOptions) (b []byte, err error) {
// Lock
r.m.Lock()
defer r.m.Unlock()
// Shared memory has not yet been opened or shared memory's name has changed
if r.shm == nil || r.shm.Name() != o.Name {
// Close previous shared memory
r.closeSharedMemory()
// Open shared memory
var shm *PosixSharedMemory
if shm, err = OpenPosixSharedMemory(o.Name); err != nil {
err = fmt.Errorf("astikit: opening shared memory failed: %w", err)
return
}
// Store attributes
r.shm = shm
}
// Copy
b = make([]byte, o.Size)
C.memcpy(unsafe.Pointer(&b[0]), r.shm.Addr(), C.size_t(o.Size))
return
}
func NewSystemVKey(projectID int, path string) (int, error) {
// Get c path
cpath := C.CString(path)

10
ipc_systemv.h Normal file
View File

@@ -0,0 +1,10 @@
#include <sys/types.h>
int astikit_ftok(char *path, int project_id, int *errno_ptr);
int astikit_sem_get(key_t key, int flags, int *errno_ptr);
int astikit_sem_close(int id, int *errno_ptr);
int astikit_sem_lock(int id, int *errno_ptr);
int astikit_sem_unlock(int id, int *errno_ptr);
void *astikit_shm_at(int id, int *errno_ptr);
int astikit_shm_get(key_t key, int size, int flags, int *errno_ptr);
int astikit_shm_close(int id, const void *addr, int *errno_ptr);

View File

@@ -7,108 +7,6 @@ import (
"testing"
)
func TestPosixSharedMemory(t *testing.T) {
sm1, err := CreatePosixSharedMemory("/test", 8)
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
defer sm1.Close()
if sm1.Addr() == nil {
t.Fatal("expected not nil, got nil")
}
if g := sm1.Size(); g <= 0 {
t.Fatalf("expected > 0, got %d", g)
}
if e, g := "test", sm1.Name(); e != g {
t.Fatalf("expected %v, got %v", e, g)
}
if _, err = CreatePosixSharedMemory("/test", 8); err == nil {
t.Fatal("expected error, got nil")
}
b1 := []byte("test")
if err := sm1.WriteBytes(b1); err != nil {
t.Fatalf("expected no error, got %s", err)
}
sm2, err := OpenPosixSharedMemory("test")
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
defer sm2.Close()
b2, err := sm2.ReadBytes(len(b1))
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
if e, g := b1, b2; !bytes.Equal(b1, b2) {
t.Fatalf("expected %s, got %s", e, g)
}
if err = sm1.Close(); err != nil {
t.Fatalf("expected no error, got %s", err)
}
if err = sm1.WriteBytes(b1); err == nil {
t.Fatal("expected error, got nil")
}
if err = sm1.Close(); err != nil {
t.Fatalf("expected no error, got %s", err)
}
if err = sm2.Close(); err != nil {
t.Fatalf("expected no error, got %s", err)
}
if _, err = sm2.ReadBytes(len(b1)); err == nil {
t.Fatal("expected error, got nil")
}
if err = sm2.Close(); err != nil {
t.Fatalf("expected no error, got %s", err)
}
}
func TestPosixVariableSizeSharedMemory(t *testing.T) {
w := NewPosixVariableSizeSharedMemoryWriter("test-1")
defer w.Close()
r := NewPosixVariableSizeSharedMemoryReader()
defer r.Close()
b1 := []byte("test")
ro1, err := w.WriteBytes(b1)
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
if e, g := w.shm.Name(), ro1.Name; e != g {
t.Fatalf("expected %s, got %s", e, g)
}
if e, g := len(b1), ro1.Size; e != g {
t.Fatalf("expected %d, got %d", e, g)
}
b2, err := r.ReadBytes(ro1)
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
if !bytes.Equal(b1, b2) {
t.Fatalf("expected %s, got %s", b1, b2)
}
b3 := make([]byte, w.shm.Size()+1)
b3[0] = 'a'
b3[len(b3)-1] = 'b'
ro2, err := w.WriteBytes(b3)
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
if ro1.Name == ro2.Name {
t.Fatal("expected different, got equalt")
}
b4, err := r.ReadBytes(ro2)
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
if !bytes.Equal(b3, b4) {
t.Fatalf("expected %s, got %s", b3, b4)
}
}
func TestNewSystemVKey(t *testing.T) {
_, err := NewSystemVKey(1, "testdata/ipc/invalid")
if err == nil {