From f7d226d0727f722337802e0b4ef449018ac87a05 Mon Sep 17 00:00:00 2001 From: Bart van Strien Date: Mon, 14 Mar 2016 17:14:49 +0100 Subject: [PATCH 1/9] Improve reaping of zombie processes on linux (resolves #1042) Sadly, it's not a complete fix for #1042, as there seems to be no good way to deal with system() in multithreaded applications. At least os.execute can return values other than -1 now. --- src/modules/system/System.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/modules/system/System.cpp b/src/modules/system/System.cpp index 61e2ef742..cd71bdbde 100755 --- a/src/modules/system/System.cpp +++ b/src/modules/system/System.cpp @@ -41,6 +41,20 @@ #pragma comment(lib, "shell32.lib") #endif +#if defined(LOVE_LINUX) +static void sigchld_handler(int sig) +{ + // Because waitpid can set errno, we need to save it. + auto old = errno; + + // Reap whilst there are children waiting to be reaped. + while (waitpid(-1, nullptr, WNOHANG) > 0) + ; + + errno = old; +} +#endif + namespace love { namespace system @@ -50,12 +64,14 @@ System::System() { #if defined(LOVE_LINUX) // Enable automatic cleanup of zombie processes + // NOTE: We're using our own handler, instead of SA_NOCLDWAIT because the + // latter breaks wait, and thus os.execute. + // NOTE: This isn't perfect, due to multithreading our SIGCHLD can happen + // on a different thread than the one calling wait(), thus causing a race. struct sigaction act = {0}; sigemptyset(&act.sa_mask); - act.sa_handler = SIG_DFL; - act.sa_flags = SA_NOCLDWAIT; - - // Requires linux 2.6 or higher, so anything remotely modern + act.sa_handler = sigchld_handler; + act.sa_flags = SA_RESTART; sigaction(SIGCHLD, &act, nullptr); #endif } From b983588d2ebc94cf85f420e7be67593167f9ef45 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 18 Mar 2016 22:58:48 -0300 Subject: [PATCH 2/9] We don't need to initialize the SDL timer subsystem to use SDL_Delay, and initializing it causes SDL to create a worker thread (which it uses for SDL_AddTimer and friends, which we don't use). --- src/modules/timer/sdl/Timer.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/modules/timer/sdl/Timer.cpp b/src/modules/timer/sdl/Timer.cpp index 528ed190e..a4d778b37 100644 --- a/src/modules/timer/sdl/Timer.cpp +++ b/src/modules/timer/sdl/Timer.cpp @@ -34,15 +34,12 @@ namespace sdl Timer::Timer() { - // Init the SDL timer system (needed for SDL_Delay.) - if (SDL_InitSubSystem(SDL_INIT_TIMER) < 0) - throw love::Exception("Could not initialize SDL timer subsystem (%s)", SDL_GetError()); + // We don't need to initialize the SDL timer subsystem for SDL_Delay to + // function - and doing so causes SDL to create a worker thread. } Timer::~Timer() { - // Quit SDL timer. - SDL_QuitSubSystem(SDL_INIT_TIMER); } const char *Timer::getName() const From 36cc48d306afe8f97bbfaa05d01699e88c489904 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 18 Mar 2016 23:01:49 -0300 Subject: [PATCH 3/9] Move the Timer::sleep implementation up from timer/sdl/Timer.cpp to timer/Timer.cpp, since it doesn't directly use any SDL-specific code. --- src/modules/timer/Timer.cpp | 7 +++++++ src/modules/timer/Timer.h | 2 +- src/modules/timer/sdl/Timer.cpp | 10 ---------- src/modules/timer/sdl/Timer.h | 3 --- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/modules/timer/Timer.cpp b/src/modules/timer/Timer.cpp index c9737842d..ce5cc7307 100644 --- a/src/modules/timer/Timer.cpp +++ b/src/modules/timer/Timer.cpp @@ -21,6 +21,7 @@ // LOVE #include "common/config.h" #include "common/int.h" +#include "common/delay.h" #include "Timer.h" #if defined(LOVE_WINDOWS) @@ -85,6 +86,12 @@ void Timer::step() } } +void Timer::sleep(double seconds) const +{ + if (seconds > 0) + love::sleep((unsigned int)(seconds*1000)); +} + double Timer::getDelta() const { return dt; diff --git a/src/modules/timer/Timer.h b/src/modules/timer/Timer.h index 53d94e843..760b9d8c1 100644 --- a/src/modules/timer/Timer.h +++ b/src/modules/timer/Timer.h @@ -50,7 +50,7 @@ public: * usually 1ms. * @param seconds The number of seconds to sleep for. **/ - virtual void sleep(double seconds) const = 0; + virtual void sleep(double seconds) const; /** * Gets the time between the last two frames, assuming step is called diff --git a/src/modules/timer/sdl/Timer.cpp b/src/modules/timer/sdl/Timer.cpp index a4d778b37..7a6f9ff37 100644 --- a/src/modules/timer/sdl/Timer.cpp +++ b/src/modules/timer/sdl/Timer.cpp @@ -20,10 +20,6 @@ // LOVE #include "Timer.h" -#include "common/delay.h" - -// SDL -#include namespace love { @@ -47,12 +43,6 @@ const char *Timer::getName() const return "love.timer.sdl"; } -void Timer::sleep(double seconds) const -{ - if (seconds > 0) - love::sleep((unsigned int)(seconds*1000)); -} - } // sdl } // timer } // love diff --git a/src/modules/timer/sdl/Timer.h b/src/modules/timer/sdl/Timer.h index 95571d7c1..cd5e2ea10 100644 --- a/src/modules/timer/sdl/Timer.h +++ b/src/modules/timer/sdl/Timer.h @@ -37,11 +37,8 @@ public: Timer(); virtual ~Timer(); - const char *getName() const override; - void sleep(double seconds) const override; - }; // Timer } // sdl From 2af327dcf94c6d25fae5601ebc55ed065c9a2ac6 Mon Sep 17 00:00:00 2001 From: Bart van Strien Date: Sun, 20 Mar 2016 10:44:36 +0100 Subject: [PATCH 4/9] Make sure android includes the right headers for System.cpp too Hopefully. --- src/modules/system/System.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/system/System.cpp b/src/modules/system/System.cpp index cd71bdbde..f63b640f2 100755 --- a/src/modules/system/System.cpp +++ b/src/modules/system/System.cpp @@ -26,20 +26,20 @@ #include #elif defined(LOVE_IOS) #include "common/ios.h" -#elif defined(LOVE_ANDROID) -#include "common/android.h" -#elif defined(LOVE_LINUX) +#elif defined(LOVE_LINUX) || defined(LOVE_ANDROID) #include -//#include -//#include #include #include +#include #elif defined(LOVE_WINDOWS) #include "common/utf8.h" #include #include #pragma comment(lib, "shell32.lib") #endif +#if defined(LOVE_ANDROID) +#include "common/android.h" +#endif #if defined(LOVE_LINUX) static void sigchld_handler(int sig) From bc932aecef9aec68d40f91e6b87dc4379ebe7a43 Mon Sep 17 00:00:00 2001 From: Bart van Strien Date: Sun, 20 Mar 2016 22:28:14 +0100 Subject: [PATCH 5/9] Move spawn.h include, because android doesn't use (or have) posix_spawn --- src/modules/system/System.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/system/System.cpp b/src/modules/system/System.cpp index f63b640f2..aa15571ea 100755 --- a/src/modules/system/System.cpp +++ b/src/modules/system/System.cpp @@ -27,7 +27,6 @@ #elif defined(LOVE_IOS) #include "common/ios.h" #elif defined(LOVE_LINUX) || defined(LOVE_ANDROID) -#include #include #include #include @@ -39,6 +38,8 @@ #endif #if defined(LOVE_ANDROID) #include "common/android.h" +#elif defined(LOVE_LINUX) +#include #endif #if defined(LOVE_LINUX) From 9ebd75985161e07be3f1c625e42b692839f21d7c Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 20 Mar 2016 22:00:24 -0300 Subject: [PATCH 6/9] Don't call glGetFloat every time love.graphics.getSystemLimits is called. --- src/modules/graphics/opengl/Graphics.cpp | 5 +---- src/modules/graphics/opengl/OpenGL.cpp | 4 ++++ src/modules/graphics/opengl/OpenGL.h | 7 +++++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 32e0e0041..fcf2b41f5 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -1661,13 +1661,10 @@ Graphics::Stats Graphics::getStats() const double Graphics::getSystemLimit(SystemLimit limittype) const { - GLfloat limits[2]; - switch (limittype) { case Graphics::LIMIT_POINT_SIZE: - glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, limits); - return (double) limits[1]; + return (double) gl.getMaxPointSize(); case Graphics::LIMIT_TEXTURE_SIZE: return (double) gl.getMaxTextureSize(); case Graphics::LIMIT_MULTI_CANVAS: diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 42319a291..358633abf 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -289,6 +289,10 @@ void OpenGL::initMaxValues() maxRenderbufferSamples = 0; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); + + GLfloat limits[2]; + glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, limits); + maxPointSize = limits[1]; } void OpenGL::initMatrices() diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 7ec940936..e4496fde4 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -377,6 +377,12 @@ public: **/ int getMaxTextureUnits() const; + /** + * Returns the maximum point size. + **/ + float getMaxPointSize() const; + + void updateTextureMemorySize(size_t oldsize, size_t newsize); /** @@ -408,6 +414,7 @@ private: int maxRenderTargets; int maxRenderbufferSamples; int maxTextureUnits; + float maxPointSize; Vendor vendor; From 8b07bad15e84390190a70b0a7cde06b4a1e3f705 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 20 Mar 2016 22:36:54 -0300 Subject: [PATCH 7/9] Fixed the build. --- src/modules/graphics/opengl/OpenGL.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 358633abf..276eaead3 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -660,6 +660,11 @@ int OpenGL::getMaxTextureUnits() const return maxTextureUnits; } +float OpenGL::getMaxPointSize() const +{ + return maxPointSize; +} + void OpenGL::updateTextureMemorySize(size_t oldsize, size_t newsize) { int64 memsize = (int64) stats.textureMemory + ((int64) newsize - (int64) oldsize); From ea2aadf88853fd298ef7bbce84ae32aafa20d796 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 21 Mar 2016 20:50:20 -0300 Subject: [PATCH 8/9] Cleaned up the code for main() a bit. --- src/love.cpp | 85 ++++++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/src/love.cpp b/src/love.cpp index 1ee6f6c00..90543acc1 100644 --- a/src/love.cpp +++ b/src/love.cpp @@ -172,45 +172,8 @@ static int l_print_sdl_log(lua_State *L) } #endif -int main(int argc, char **argv) +static int runlove(int argc, char **argv) { - int retval = 0; - -#ifdef LOVE_IOS - int orig_argc = argc; - char **orig_argv = argv; - - // on iOS we should never programmatically exit the app, so we'll just - // "restart" when that is attempted. Games which use threads might cause - // some issues if the threads aren't cleaned up properly... - while (true) - { - argc = orig_argc; - argv = orig_argv; -#endif - -#ifdef LOVE_LEGENDARY_APP_ARGV_HACK - int hack_argc = 0; - char **hack_argv = 0; - get_app_arguments(argc, argv, hack_argc, hack_argv); - argc = hack_argc; - argv = hack_argv; -#endif // LOVE_LEGENDARY_APP_ARGV_HACK - - if (strcmp(LOVE_VERSION_STRING, love_version()) != 0) - { - printf("Version mismatch detected!\nLOVE binary is version %s\n" - "LOVE library is version %s\n", LOVE_VERSION_STRING, love_version()); - return 1; - } - - // Oh, you just want the version? Okay! - if (argc > 1 && strcmp(argv[1], "--version") == 0) - { - printf("LOVE %s (%s)\n", love_version(), love_codename()); - return 0; - } - // Create the virtual machine. lua_State *L = luaL_newstate(); luaL_openlibs(L); @@ -269,12 +232,52 @@ int main(int argc, char **argv) // Call the returned boot function. lua_call(L, 0, 1); + int retval = 0; if (lua_isnumber(L, -1)) retval = (int) lua_tonumber(L, -1); lua_close(L); -#if defined(LOVE_LEGENDARY_APP_ARGV_HACK) + return retval; +} + +int main(int argc, char **argv) +{ + int retval = 0; + +#ifdef LOVE_LEGENDARY_APP_ARGV_HACK + int hack_argc = 0; + char **hack_argv = 0; + get_app_arguments(argc, argv, hack_argc, hack_argv); + argc = hack_argc; + argv = hack_argv; +#endif // LOVE_LEGENDARY_APP_ARGV_HACK + + if (strcmp(LOVE_VERSION_STRING, love_version()) != 0) + { + printf("Version mismatch detected!\nLOVE binary is version %s\n" + "LOVE library is version %s\n", LOVE_VERSION_STRING, love_version()); + return 1; + } + + // Oh, you just want the version? Okay! + if (argc > 1 && strcmp(argv[1], "--version") == 0) + { + printf("LOVE %s (%s)\n", love_version(), love_codename()); + return 0; + } + +#ifdef LOVE_IOS + // on iOS we should never programmatically exit the app, so we'll just + // "restart" when that is attempted. Games which use threads might cause + // some issues if the threads aren't cleaned up properly... + while (true) +#endif + { + retval = runlove(argc, argv); + } + +#if defined(LOVE_LEGENDARY_APP_ARGV_HACK) && !defined(LOVE_IOS) if (hack_argv) { for (int i = 0; i Date: Tue, 22 Mar 2016 18:05:26 -0300 Subject: [PATCH 9/9] Fix love.window.setMode crashing if a Canvas is active. --- src/modules/graphics/opengl/Canvas.cpp | 3 ++- src/modules/graphics/opengl/Graphics.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index d706148dd..97949a67d 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -521,7 +521,8 @@ void Canvas::stopGrab(bool switchingToOtherCanvas) // Make sure the canvas texture is up to date if we're using MSAA. resolveMSAA(false); - gl.matrices.projection.pop_back(); + if (gl.matrices.projection.size() > 1) + gl.matrices.projection.pop_back(); if (!switchingToOtherCanvas) { diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index fcf2b41f5..9a7d2d2a6 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -252,8 +252,6 @@ bool Graphics::setMode(int width, int height) created = true; - setViewportSize(width, height); - // Enable blending glEnable(GL_BLEND); @@ -310,6 +308,8 @@ bool Graphics::setMode(int width, int height) if (quadIndices == nullptr) quadIndices = new QuadIndices(20); + setViewportSize(width, height); + // Restore the graphics state. restoreState(states.back());