1//
2// NamedEvent_UNIX.cpp
3//
4// Library: Foundation
5// Package: Processes
6// Module: NamedEvent
7//
8// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/NamedEvent_UNIX.h"
16#include "Poco/Format.h"
17#include "Poco/Exception.h"
18#include <fcntl.h>
19#include <sys/stat.h>
20#include <errno.h>
21#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX) || defined(__EMSCRIPTEN__)
22#include <semaphore.h>
23#else
24#include <unistd.h>
25#include <sys/types.h>
26#include <sys/ipc.h>
27#include <sys/sem.h>
28#endif
29
30
31namespace Poco {
32
33
34#if (POCO_OS == POCO_OS_LINUX) || (POCO_OS == POCO_OS_ANDROID) || (POCO_OS == POCO_OS_CYGWIN) || (POCO_OS == POCO_OS_FREE_BSD) || (POCO_OS == POCO_OS_NACL)
35 union semun
36 {
37 int val;
38 struct semid_ds* buf;
39 unsigned short int* array;
40 struct seminfo* __buf;
41 };
42#elif (POCO_OS == POCO_OS_HPUX)
43 union semun
44 {
45 int val;
46 struct semid_ds* buf;
47 ushort* array;
48 };
49#endif
50
51
52NamedEventImpl::NamedEventImpl(const std::string& name):
53 _name(name)
54{
55 std::string fileName = getFileName();
56#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX) || defined(__EMSCRIPTEN__)
57 _sem = sem_open(fileName.c_str(), O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO, 0);
58 if ((long) _sem == (long) SEM_FAILED)
59 throw SystemException(Poco::format("cannot create named mutex %s (sem_open() failed, errno=%d)", fileName, errno), _name);
60#else
61 int fd = open(fileName.c_str(), O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
62 if (fd != -1)
63 close(fd);
64 else
65 throw SystemException(Poco::format("cannot create named event %s (lockfile)", fileName), _name);
66 key_t key = ftok(fileName.c_str(), 'p');
67 if (key == -1)
68 throw SystemException(Poco::format("cannot create named mutex %s (ftok() failed, errno=%d)", fileName, errno), _name);
69 _semid = semget(key, 1, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | IPC_CREAT | IPC_EXCL);
70 if (_semid >= 0)
71 {
72 union semun arg;
73 arg.val = 0;
74 semctl(_semid, 0, SETVAL, arg);
75 }
76 else if (errno == EEXIST)
77 {
78 _semid = semget(key, 1, 0);
79 }
80 else throw SystemException(Poco::format("cannot create named mutex %s (semget() failed, errno=%d)", fileName, errno), _name);
81#endif // defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX) || defined(__EMSCRIPTEN__)
82}
83
84
85NamedEventImpl::~NamedEventImpl()
86{
87#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX) || defined(__EMSCRIPTEN__)
88 sem_close(_sem);
89#endif
90}
91
92
93void NamedEventImpl::setImpl()
94{
95#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX) || defined(__EMSCRIPTEN__)
96 if (sem_post(_sem) != 0)
97 throw SystemException("cannot set named event", _name);
98#else
99 struct sembuf op;
100 op.sem_num = 0;
101 op.sem_op = 1;
102 op.sem_flg = 0;
103 if (semop(_semid, &op, 1) != 0)
104 throw SystemException("cannot set named event", _name);
105#endif
106}
107
108
109void NamedEventImpl::waitImpl()
110{
111#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX) || defined(__EMSCRIPTEN__)
112 int err;
113 do
114 {
115 err = sem_wait(_sem);
116 }
117 while (err && errno == EINTR);
118 if (err) throw SystemException("cannot wait for named event", _name);
119#else
120 struct sembuf op;
121 op.sem_num = 0;
122 op.sem_op = -1;
123 op.sem_flg = 0;
124 int err;
125 do
126 {
127 err = semop(_semid, &op, 1);
128 }
129 while (err && errno == EINTR);
130 if (err) throw SystemException("cannot wait for named event", _name);
131#endif
132}
133
134
135std::string NamedEventImpl::getFileName()
136{
137#if defined(sun) || defined(__APPLE__) || defined(__QNX__)
138 std::string fn = "/";
139#else
140 std::string fn = "/tmp/";
141#endif
142 fn.append(_name);
143 fn.append(".event");
144 return fn;
145}
146
147
148} // namespace Poco
149