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 | |
31 | namespace Poco { |
32 | |
33 | |
34 | #if (POCO_OS == POCO_OS_LINUX) || (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 | |
52 | NamedEventImpl::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 | |
85 | NamedEventImpl::~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 | |
93 | void 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 | |
109 | void 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 | |
135 | std::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 | |