]> git.ipfire.org Git - thirdparty/squid.git/blob - src/base/TextException.cc
Detail client closures of CONNECT tunnels during TLS handshake (#691)
[thirdparty/squid.git] / src / base / TextException.cc
1 /*
2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 #include "squid.h"
10 #include "base/TextException.h"
11 #include "sbuf/SBuf.h"
12
13 #include <iostream>
14 #include <sstream>
15 #include <unordered_map>
16
17 /// a standard CoW string; avoids noise and circular dependencies of SBuf
18 typedef std::runtime_error WhatString;
19
20 /// a collection of strings indexed by pointers to their creator objects
21 typedef std::unordered_multimap<const void*, WhatString> WhatStrings;
22
23 /// requested what() strings of alive TextException objects
24 static WhatStrings *WhatStrings_ = nullptr;
25
26 TextException::TextException(SBuf message, const SourceLocation &location):
27 TextException(message.c_str(), location)
28 {}
29
30 TextException::~TextException() throw()
31 {
32 if (WhatStrings_)
33 WhatStrings_->erase(this); // there only if what() has been called
34 }
35
36 std::ostream &
37 TextException::print(std::ostream &os) const
38 {
39 os << std::runtime_error::what() <<
40 Debug::Extra << "exception location: " << where;
41 // TODO: ...error_detail: " << (ERR_DETAIL_EXCEPTION_START+id());
42 return os;
43 }
44
45 const char *
46 TextException::what() const throw()
47 {
48 std::ostringstream os;
49 print(os);
50 const WhatString result(os.str());
51
52 // extend result.c_str() lifetime to this object lifetime
53 if (!WhatStrings_)
54 WhatStrings_ = new WhatStrings;
55 // *this could change, but we must preserve old results for they may be used
56 WhatStrings_->emplace(std::make_pair(this, result));
57
58 return result.what();
59 }
60
61 std::ostream &
62 operator <<(std::ostream &os, const TextException &ex)
63 {
64 ex.print(os);
65 return os;
66 }
67
68 std::ostream &
69 CurrentException(std::ostream &os)
70 {
71 if (std::current_exception()) {
72 try {
73 throw; // re-throw to recognize the exception type
74 }
75 catch (const TextException &ex) {
76 os << ex; // optimization: this is a lot cheaper than what() below
77 }
78 catch (const std::exception &ex) {
79 os << ex.what();
80 }
81 catch (...) {
82 os << "[unknown exception type]";
83 }
84 } else {
85 os << "[no active exception]";
86 }
87 return os;
88 }
89