Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.2] Added Linux sanitizer with xvfb to github workspace #40994

Merged
merged 1 commit into from
Oct 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions .github/workflows/linux_builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,83 @@ jobs:
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
run: |
scons -j2 verbose=yes warnings=all werror=yes platform=x11 target=release tools=no module_mono_enabled=yes mono_glue=no

linux-sanitizer:
runs-on: "ubuntu-20.04"
name: Editor and exported project with sanitizers(target=debug/release, tools=yes/no, debug_symbols=yes/full, use_ubsan=yes, use_asan=yes)

steps:
- uses: actions/checkout@v2

# Azure repositories are not reliable, we need to prevent azure giving us packages.
- name: Make apt sources.list use the default Ubuntu repositories
run: |
sudo cp -f misc/ci/sources.list /etc/apt/sources.list
sudo apt-get update

# Install all packages (except scons)
- name: Configure dependencies
run: |
sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \
libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev yasm \
xvfb wget2 unzip

# Upload cache on completion and check it out now
- name: Load .scons_cache directory
id: linux-editor-cache
uses: actions/cache@v2
with:
path: ${{github.workspace}}/.scons_cache/
key: ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
restore-keys: |
${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}
${{github.job}}-${{env.GODOT_BASE_BRANCH}}

# Use python 3.x release (works cross platform; best to keep self contained in it's own step)
- name: Set up Python 3.x
uses: actions/setup-python@v2
with:
# Semantic version range syntax or exact version of a Python version
python-version: '3.x'
# Optional - x64 or x86 architecture, defaults to x64
architecture: 'x64'

# Setup scons, print python version and scons version info, so if anything is broken it won't run the build.
- name: Configuring Python packages
run: |
python -c "import sys; print(sys.version)"
python -m pip install scons
python --version
scons --version

# We should always be explicit with our flags usage here since it's gonna be sure to always set those flags
- name: Compilation
env:
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
run: |
scons -j2 verbose=yes warnings=all werror=yes platform=x11 tools=yes target=debug use_ubsan=yes use_asan=yes
scons -j2 verbose=yes warnings=all werror=yes platform=x11 tools=no target=release debug_symbols=full use_ubsan=yes use_asan=yes

# Download and test project to check leaks and invalid memory usage
- name: Importing and running project project
run: |
wget2 https://github.com/qarmin/RegressionTestProject/archive/3.2.zip
unzip 3.2.zip
mv "RegressionTestProject-3.2" "test_project"
DRI_PRIME=0 timeout 25s xvfb-run bin/godot.x11.tools.64s -e --path test_project 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt
DRI_PRIME=0 xvfb-run bin/godot.x11.tools.64s 20 --video-driver GLES3 --path test_project 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt

# Export project and run it to check for possible leaks and invalid memory usage
- name: Exporting and running project
run: |
mkdir exported_project
sed -i 's:PATH_TO_CHANGE:'`pwd`/bin/godot.x11.debug.64s':' test_project/export_presets.cfg
cd test_project
DRI_PRIME=0 xvfb-run ../bin/godot.x11.tools.64s --export-debug "Linux/X11" ../exported_project/test_project 2>&1 | tee sanitizers_log.txt || true
cd ..
misc/scripts/check_ci_log.py sanitizers_log.txt
DRI_PRIME=0 xvfb-run exported_project/test_project 20 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt
3 changes: 3 additions & 0 deletions editor/editor_resource_preview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
}
r_texture = generated;

if (!EditorNode::get_singleton()->get_theme_base())
return;

int small_thumbnail_size = EditorNode::get_singleton()->get_theme_base()->get_icon("Object", "EditorIcons")->get_width(); // Kind of a workaround to retrieve the default icon size
small_thumbnail_size *= EDSCALE;

Expand Down
1 change: 1 addition & 0 deletions editor/editor_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,7 @@ void EditorSettings::create() {
String config_file_name = "editor_settings-" + itos(VERSION_MAJOR) + ".tres";
config_file_path = config_dir.plus_file(config_file_name);
if (!dir->file_exists(config_file_name)) {
memdelete(dir);
goto fail;
}

Expand Down
51 changes: 51 additions & 0 deletions misc/scripts/check_ci_log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

if len(sys.argv) < 2:
print("ERROR: You must run program with file name as argument.")
sys.exit(1)

fname = sys.argv[1]

fileread = open(fname.strip(), "r")
file_contents = fileread.read()

# If find "ERROR: AddressSanitizer:", then happens invalid read or write
# This is critical bug, so we need to fix this as fast as possible

if file_contents.find("ERROR: AddressSanitizer:") != -1:
print("FATAL ERROR: An incorrectly used memory was found.")
sys.exit(1)

# There is also possible, that program crashed with or without backtrace.

if (
file_contents.find("Program crashed with signal") != -1
or file_contents.find("Dumping the backtrace") != -1
or file_contents.find("Segmentation fault (core dumped)") != -1
):
print("FATAL ERROR: Godot has been crashed.")
sys.exit(1)

# Finding memory leaks in Godot is quite difficult, because we need to take into
# account leaks also in external libraries. They are usually provided without
# debugging symbols, so the leak report from it usually has only 2/3 lines,
# so searching for 5 element - "#4 0x" - should correctly detect the vast
# majority of memory leaks

if file_contents.find("ERROR: LeakSanitizer:") != -1:
if file_contents.find("#4 0x") != -1:
print("ERROR: Memory leak was found")
sys.exit(1)

# It may happen that Godot detects leaking nodes/resources and removes them, so
# this possibility should also be handled as a potential error, even if
# LeakSanitizer doesn't report anything

if file_contents.find("ObjectDB instances leaked at exit") != -1:
print("ERROR: Memory leak was found")
sys.exit(1)

sys.exit(0)
20 changes: 12 additions & 8 deletions platform/osx/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,26 @@ def configure(env):
## Build type

if env["target"] == "release":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O3", "-fomit-frame-pointer", "-ftree-vectorize", "-msse2"])
else: # optimize for size
env.Prepend(CCFLAGS=["-Os", "-ftree-vectorize", "-msse2"])
if env["debug_symbols"] != "full":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O3", "-fomit-frame-pointer", "-ftree-vectorize", "-msse2"])
else: # optimize for size
env.Prepend(CCFLAGS=["-Os", "-ftree-vectorize", "-msse2"])

if env["debug_symbols"] == "yes":
env.Prepend(CCFLAGS=["-g1"])
if env["debug_symbols"] == "full":
env.Prepend(CCFLAGS=["-g2"])

elif env["target"] == "release_debug":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O2"])
else: # optimize for size
env.Prepend(CCFLAGS=["-Os"])
if env["debug_symbols"] != "full":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O2"])
else: # optimize for size
env.Prepend(CCFLAGS=["-Os"])

env.Prepend(CPPDEFINES=["DEBUG_ENABLED"])

if env["debug_symbols"] == "yes":
env.Prepend(CCFLAGS=["-g1"])
if env["debug_symbols"] == "full":
Expand Down
18 changes: 10 additions & 8 deletions platform/windows/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,19 +177,21 @@ def configure_msvc(env, manual_msvc_config):
# Build type

if env["target"] == "release":
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["/O2"])
else: # optimize for size
env.Append(CCFLAGS=["/O1"])
if env["debug_symbols"] != "full":
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["/O2"])
else: # optimize for size
env.Append(CCFLAGS=["/O1"])
env.Append(LINKFLAGS=["/SUBSYSTEM:WINDOWS"])
env.Append(LINKFLAGS=["/ENTRY:mainCRTStartup"])
env.Append(LINKFLAGS=["/OPT:REF"])

elif env["target"] == "release_debug":
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["/O2"])
else: # optimize for size
env.Append(CCFLAGS=["/O1"])
if env["debug_symbols"] != "full":
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["/O2"])
else: # optimize for size
env.Append(CCFLAGS=["/O1"])
env.AppendUnique(CPPDEFINES=["DEBUG_ENABLED"])
env.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"])
env.Append(LINKFLAGS=["/OPT:REF"])
Expand Down
38 changes: 27 additions & 11 deletions platform/x11/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,24 @@ def configure(env):
## Build type

if env["target"] == "release":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O3"])
else: # optimize for size
env.Prepend(CCFLAGS=["-Os"])
if env["debug_symbols"] != "full":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O3"])
else: # optimize for size
env.Prepend(CCFLAGS=["-Os"])

if env["debug_symbols"] == "yes":
env.Prepend(CCFLAGS=["-g1"])
if env["debug_symbols"] == "full":
env.Prepend(CCFLAGS=["-g2"])

elif env["target"] == "release_debug":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O2"])
else: # optimize for size
env.Prepend(CCFLAGS=["-Os"])
if env["debug_symbols"] != "full":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O2"])
else: # optimize for size
env.Prepend(CCFLAGS=["-Os"])

env.Prepend(CPPDEFINES=["DEBUG_ENABLED"])

if env["debug_symbols"] == "yes":
Expand Down Expand Up @@ -146,11 +149,24 @@ def configure(env):
env.extra_suffix += "s"

if env["use_ubsan"]:
env.Append(CCFLAGS=["-fsanitize=undefined"])
env.Append(LINKFLAGS=["-fsanitize=undefined"])
env.Append(
CCFLAGS=[
"-fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin"
]
)

if env["use_llvm"]:
env.Append(
CCFLAGS=[
"-fsanitize=nullability-return,nullability-arg,function,nullability-assign,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation"
]
)
else:
env.Append(CCFLAGS=["-fsanitize=bounds-strict"])
env.Append(LINKFLAGS=["-fsanitize=undefined"])

if env["use_asan"]:
env.Append(CCFLAGS=["-fsanitize=address"])
env.Append(CCFLAGS=["-fsanitize=address,pointer-subtract,pointer-compare"])
env.Append(LINKFLAGS=["-fsanitize=address"])

if env["use_lsan"]:
Expand Down