Skip to content

Commit ac54be7

Browse files
committed
reconnect cannot reconnect when you are out of authority
1 parent a3b0a96 commit ac54be7

File tree

4 files changed

+78
-36
lines changed

4 files changed

+78
-36
lines changed

demo/win_service/client/main.cpp

+15-2
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,27 @@ int _tmain (int argc, TCHAR *argv[]) {
1111
ipc::channel ipc_r{ipc::prefix{"Global\\"}, "service ipc r", ipc::receiver};
1212
ipc::channel ipc_w{ipc::prefix{"Global\\"}, "service ipc w", ipc::sender};
1313
while (1) {
14+
if (!ipc_r.reconnect(ipc::receiver)) {
15+
Sleep(1000);
16+
continue;
17+
}
1418
auto msg = ipc_r.recv();
1519
if (msg.empty()) {
1620
_tprintf(_T("My Sample Client: message recv error\n"));
17-
return -1;
21+
ipc_r.disconnect();
22+
continue;
1823
}
1924
printf("My Sample Client: message recv: [%s]\n", (char const *)msg.data());
20-
while (!ipc_w.send("Copy.")) {
25+
for (;;) {
26+
if (!ipc_w.reconnect(ipc::sender)) {
27+
Sleep(1000);
28+
continue;
29+
}
30+
if (ipc_w.send("Copy.")) {
31+
break;
32+
}
2133
_tprintf(_T("My Sample Client: message send error\n"));
34+
ipc_w.disconnect();
2235
Sleep(1000);
2336
}
2437
_tprintf(_T("My Sample Client: message send [Copy]\n"));

src/libipc/ipc.cpp

+45-27
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,27 @@ struct conn_info_head {
112112
ipc::shm::handle acc_h_;
113113

114114
conn_info_head(char const * prefix, char const * name)
115-
: prefix_ {ipc::make_string(prefix)}
116-
, name_ {ipc::make_string(name)}
117-
, cc_id_ {}
118-
, cc_waiter_{ipc::make_prefix(prefix_, {"CC_CONN__", name_}).c_str()}
119-
, wt_waiter_{ipc::make_prefix(prefix_, {"WT_CONN__", name_}).c_str()}
120-
, rd_waiter_{ipc::make_prefix(prefix_, {"RD_CONN__", name_}).c_str()}
121-
, acc_h_ {ipc::make_prefix(prefix_, {"AC_CONN__", name_}).c_str(), sizeof(acc_t)} {
115+
: prefix_{ipc::make_string(prefix)}
116+
, name_ {ipc::make_string(name)}
117+
, cc_id_ {} {}
118+
119+
void init() {
120+
if (!cc_waiter_.valid()) cc_waiter_.open(ipc::make_prefix(prefix_, {"CC_CONN__", name_}).c_str());
121+
if (!wt_waiter_.valid()) wt_waiter_.open(ipc::make_prefix(prefix_, {"WT_CONN__", name_}).c_str());
122+
if (!rd_waiter_.valid()) rd_waiter_.open(ipc::make_prefix(prefix_, {"RD_CONN__", name_}).c_str());
123+
if (!acc_h_.valid()) acc_h_.acquire(ipc::make_prefix(prefix_, {"AC_CONN__", name_}).c_str(), sizeof(acc_t));
124+
if (cc_id_ != 0) {
125+
return;
126+
}
122127
acc_t *pacc = cc_acc(prefix_);
123-
if (pacc != nullptr) {
124-
cc_id_ = pacc->fetch_add(1, std::memory_order_relaxed);
128+
if (pacc == nullptr) {
129+
// Failed to obtain the global accumulator.
130+
return;
131+
}
132+
cc_id_ = pacc->fetch_add(1, std::memory_order_relaxed) + 1;
133+
if (cc_id_ == 0) {
134+
// The identity cannot be 0.
135+
cc_id_ = pacc->fetch_add(1, std::memory_order_relaxed) + 1;
125136
}
126137
}
127138

@@ -362,12 +373,18 @@ struct queue_generator {
362373
queue_t que_;
363374

364375
conn_info_t(char const * pref, char const * name)
365-
: conn_info_head{pref, name}
366-
, que_{ipc::make_prefix(prefix_, {
367-
"QU_CONN__",
368-
ipc::to_string(DataSize), "__",
369-
ipc::to_string(AlignSize), "__",
370-
name}).c_str()} {}
376+
: conn_info_head{pref, name} { init(); }
377+
378+
void init() {
379+
conn_info_head::init();
380+
if (!que_.valid()) {
381+
que_.open(ipc::make_prefix(prefix_, {
382+
"QU_CONN__",
383+
ipc::to_string(DataSize), "__",
384+
ipc::to_string(AlignSize), "__",
385+
this->name_}).c_str());
386+
}
387+
}
371388

372389
void disconnect_receiver() {
373390
bool dis = que_.disconnect();
@@ -397,6 +414,18 @@ constexpr static queue_t* queue_of(ipc::handle_t h) noexcept {
397414

398415
/* API implementations */
399416

417+
static bool connect(ipc::handle_t * ph, ipc::prefix pref, char const * name, bool start_to_recv) {
418+
assert(ph != nullptr);
419+
if (*ph == nullptr) {
420+
*ph = ipc::mem::alloc<conn_info_t>(pref.str, name);
421+
}
422+
return reconnect(ph, start_to_recv);
423+
}
424+
425+
static bool connect(ipc::handle_t * ph, char const * name, bool start_to_recv) {
426+
return connect(ph, {nullptr}, name, start_to_recv);
427+
}
428+
400429
static void disconnect(ipc::handle_t h) {
401430
auto que = queue_of(h);
402431
if (que == nullptr) {
@@ -414,6 +443,7 @@ static bool reconnect(ipc::handle_t * ph, bool start_to_recv) {
414443
if (que == nullptr) {
415444
return false;
416445
}
446+
info_of(*ph)->init();
417447
if (start_to_recv) {
418448
que->shut_sending();
419449
if (que->connect()) { // wouldn't connect twice
@@ -429,18 +459,6 @@ static bool reconnect(ipc::handle_t * ph, bool start_to_recv) {
429459
return que->ready_sending();
430460
}
431461

432-
static bool connect(ipc::handle_t * ph, ipc::prefix pref, char const * name, bool start_to_recv) {
433-
assert(ph != nullptr);
434-
if (*ph == nullptr) {
435-
*ph = ipc::mem::alloc<conn_info_t>(pref.str, name);
436-
}
437-
return reconnect(ph, start_to_recv);
438-
}
439-
440-
static bool connect(ipc::handle_t * ph, char const * name, bool start_to_recv) {
441-
return connect(ph, {nullptr}, name, start_to_recv);
442-
}
443-
444462
static void destroy(ipc::handle_t h) {
445463
disconnect(h);
446464
ipc::mem::free(info_of(h));

src/libipc/platform/win/shm_win.cpp

+11-6
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,26 @@ id_t acquire(char const * name, std::size_t size, unsigned mode) {
3737
// Opens a named file mapping object.
3838
if (mode == open) {
3939
h = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, fmt_name.c_str());
40+
if (h == NULL) {
41+
ipc::error("fail OpenFileMapping[%d]: %s\n", static_cast<int>(::GetLastError()), name);
42+
return nullptr;
43+
}
4044
}
4145
// Creates or opens a named file mapping object for a specified file.
4246
else {
4347
h = ::CreateFileMapping(INVALID_HANDLE_VALUE, detail::get_sa(), PAGE_READWRITE | SEC_COMMIT,
4448
0, static_cast<DWORD>(size), fmt_name.c_str());
49+
DWORD err = ::GetLastError();
4550
// If the object exists before the function call, the function returns a handle to the existing object
4651
// (with its current size, not the specified size), and GetLastError returns ERROR_ALREADY_EXISTS.
47-
if ((mode == create) && (::GetLastError() == ERROR_ALREADY_EXISTS)) {
48-
::CloseHandle(h);
52+
if ((mode == create) && (err == ERROR_ALREADY_EXISTS)) {
53+
if (h != NULL) ::CloseHandle(h);
4954
h = NULL;
5055
}
51-
}
52-
if (h == NULL) {
53-
ipc::error("fail CreateFileMapping/OpenFileMapping[%d]: %s\n", static_cast<int>(::GetLastError()), name);
54-
return nullptr;
56+
if (h == NULL) {
57+
ipc::error("fail CreateFileMapping[%d]: %s\n", static_cast<int>(err), name);
58+
return nullptr;
59+
}
5560
}
5661
auto ii = mem::alloc<id_info_t>();
5762
ii->h_ = h;

src/libipc/queue.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class queue_base : public queue_conn {
104104

105105
explicit queue_base(char const * name)
106106
: queue_base{} {
107-
elems_ = open<elems_t>(name);
107+
elems_ = queue_conn::template open<elems_t>(name);
108108
}
109109

110110
explicit queue_base(elems_t * elems) noexcept
@@ -117,6 +117,12 @@ class queue_base : public queue_conn {
117117
base_t::close();
118118
}
119119

120+
bool open(char const * name) noexcept {
121+
base_t::close();
122+
elems_ = queue_conn::template open<elems_t>(name);
123+
return elems_ != nullptr;
124+
}
125+
120126
elems_t * elems() noexcept { return elems_; }
121127
elems_t const * elems() const noexcept { return elems_; }
122128

0 commit comments

Comments
 (0)