UPnPsdk 0.1
Universal Plug and Play +, Software Development Kit
 
Loading...
Searching...
No Matches
connection_common.cpp
Go to the documentation of this file.
1#ifndef _MSC_VER
2
3// Copyright (C) 2023+ GPL 3 and higher by Ingo Höft, <Ingo@Hoeft-online.de>
4// Redistribution only with this Copyright remark. Last modified: 2024-08-18
12#include <UPnPsdk/synclog.hpp>
13
15namespace UPnPsdk {
16
17CSigpipe_scoped::CSigpipe_scoped() {
18 TRACE("Construct CSigpipe_scoped");
19 /* We want to ignore possible SIGPIPE that we can generate on write. SIGPIPE
20 * is delivered *synchronously* and *only* to the thread doing the write. So
21 * if it is reported as already pending (which means the thread blocks it),
22 * then we do nothing: if we generate SIGPIPE, it will be merged with the
23 * pending one (there's no queuing), and that suits us well. If it is not
24 * pending, we block it in this thread (and we avoid changing signal action,
25 * because it is per-process). */
26 sigset_t pending;
27 sigemptyset(&pending);
28 sigpending(&pending);
29
30 m_sigpipe_pending = sigismember(&pending, SIGPIPE);
31 if (!m_sigpipe_pending) {
32 sigset_t sigpipe_mask;
33 sigemptyset(&sigpipe_mask);
34 sigaddset(&sigpipe_mask, SIGPIPE);
35
36 sigset_t blocked;
37 sigemptyset(&blocked);
38 pthread_sigmask(SIG_BLOCK, &sigpipe_mask, &blocked);
39
40 /* Maybe is was blocked already? */
41 m_sigpipe_unblock = !sigismember(&blocked, SIGPIPE);
42 }
43}
44
45CSigpipe_scoped::~CSigpipe_scoped() {
46 TRACE("Destruct CSigpipe_scoped");
47 /* If SIGPIPE was pending already we do nothing. Otherwise, if it become
48 * pending (i.e., we generated it), then we sigwait() it (thus clearing
49 * pending status). Then we unblock SIGPIPE, but only if it were us who
50 * blocked it. */
51 if (!m_sigpipe_pending) {
52 sigset_t sigpipe_mask;
53 sigemptyset(&sigpipe_mask);
54 sigaddset(&sigpipe_mask, SIGPIPE);
55
56 // I cannot use sigtimedwait() because it isn't available on
57 // macOS/OpenBSD. I workaround it with sigpending() and sigwait() to
58 // ensure that sigwait() never blocks.
59 sigset_t pending;
60 while (true) {
61 /* Protect ourselves from a situation when SIGPIPE was sent by
62 * the user to the whole process, and was delivered to other
63 * thread before we had a chance to wait for it. */
64 sigemptyset(&pending);
65 sigpending(&pending);
66 if (sigismember(&pending, SIGPIPE)) {
67 int sig; // Only return buffer, not used.
68 sigwait(&sigpipe_mask, &sig);
69 } else
70 break;
71 }
72
73 if (m_sigpipe_unblock)
74 pthread_sigmask(SIG_UNBLOCK, &sigpipe_mask, NULL);
75 }
76}
77
78} // namespace UPnPsdk
80
81#endif
Declaration of common used classes and free functions for network connections.
Reengineered Object Oriented UPnP+ program code.
Define macro for synced logging to the console for detailed info and debug.