It turns out this was already enabled on MSVC (due to /EHsc), but let's
enable it on other platforms as well.
Exception handling comes with a huge caveat: SourceMod and SourcePawn
are not exception safe. Not only do they predate usable STL (C++11),
they often predate C++03, and sometimes even C++ itself. There are many
places we do not use RAII, or where we accumulate state in a way that
cannot be interrupted.
By enabling exceptions, we are NOT inviting general try/catch. We are
still assuming that a `throw` anywhere within SourceMod will ultimately
result in a crash.
However, as we enable more and more STL, we are losing the ability to
gracefully handle constructor failures and malloc failures. So try-catch
is now enabled. It should only be used in the narrowest of
circumstances:
- When an exception can be thrown by a library call, and
- There is no way "a priori" to tell if an exception will be thrown
(for example, std::bad_alloc or std::system_error), and
- Handling the exception is meaningful.
Generally malloc failures should not be considered meaningful. Once
memory is exhausted, the program will crash or be OOM-killed, so there's
no point in handling the failure. However, cases where the allocation
amount is variable may be meaningful to handle. A simple example would
be CDataPack, where if a plugin leaks entries, it's better to handle
this gracefully given that vector growth is geometric. Another example
might be reads of a massive file or network request into a buffer.
These cases should be rare, given that memory pressure is usually
fatal to srcds anyway. But if you've decided to handle an exception,
the try-catch block should be as narrow as possible. For example,
the following is erroneous:
ke::Maybe<SomeGiganticThing> object;
try {
object.init();
} catch (const std::bad_alloc&) {
}
`ke::Maybe` is not threadsafe, and this can leak. Basically, do as
little as possible in try blocks, and use them sparingly, because
they're very difficult to audit.
We are also not inviting use of `throw`, as auditing it is even more
complex than try/catch. It is better to abort(), or use boolean
returns and two-stage object initialization.
|
||
|---|---|---|
| .github | ||
| bridge/include | ||
| configs | ||
| core | ||
| editor | ||
| extensions | ||
| gamedata | ||
| licenses | ||
| loader | ||
| plugins | ||
| public | ||
| sourcepawn@2075605089 | ||
| tools | ||
| translations | ||
| versionlib | ||
| .arcconfig | ||
| .gitattributes | ||
| .gitignore | ||
| .gitmodules | ||
| .travis.yml | ||
| AMBuildScript | ||
| changelog.txt | ||
| configure.py | ||
| product.version | ||
| pushbuild.txt | ||
| README.md | ||
SourceMod
General
- SourceMod website: Source Engine scripting and server administration
- Forum: Discussion forum including plugin/extension development
- General documentation: Miscellaneous information about SourceMod
- Stable builds: The latest stable SourceMod releases
- Dev builds: Builds of recent development versions
Development
- Issue tracker: Issues that require back and forth communication
- Building SourceMod: Instructions on how to build SourceMod itself using AMBuild
- SourcePawn scripting: SourcePawn examples and introduction to the language
- SourceMod plugin API: Online SourceMod plugin API reference generated from the include files
- SourceMod extension development: C++ examples and introduction to various extension interfaces
Contact
License
SourceMod is licensed under the GNU General Public License version 3. Special exceptions are outlined in the LICENSE.txt file inside of the licenses folder.