1. pygame
  2. pygame
  3. pygame

Issues

Issue #98 wontfix

pygame.event.pump in a separate process causes crash on mac OS 10.7

Mike Lawrence
created an issue

I use pygame for running experiments in cognitive science, and often I have heavy I/O demands so I like to fork off these tasks to separate processes (when using a multi-core machine) to improve performance of my code. However, I encountered a scenario where some code works on my colleague's linux machine (Ubuntu LTS), but not on my mac. Below is code representing a minimal reproducible example. My mac is a 2011 Macbook Air running 10.7.2 and using the default python 2.7.1. I tried both pygame as installed via pre-built binary, and I also then tried after installing both SDL and pygame from source.

{{{

!python

import pygame import multiprocessing pygame.init()

def f(): while True: pygame.event.pump() #if this is replaced by pass, this code works

p = multiprocessing.Process(target=f) p.start()

while True: pass }}}

As noted in the code, it seems that the culprit is putting pygame.event.pump() in a separate process. When I run this on my mac, I first get the following printed repeatedly in terminal: {{{ The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec(). Break on _THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY_YOU_MUST_EXEC() to debug. }}} Then I get a crash report as copied in the attached file.

Any suggestions for how to fix this?

Comments (6)

  1. René Dudfield
    • changed status to open

    Woh, that is a very long variable name :)

    You might be able to use this as a work around, it works on Lion for me:

    import pygame
    import os
    import multiprocessing
    pygame.init()
    
    parent_pid = os.getpid()
    
    
    def f():
        global parent_pid
        while True:
            if os.getpid() == parent_pid:
                pygame.event.pump() #if this is replaced by pass, this code works
    
            s = pygame.Surface((1,1))
            s.fill((233,233,245))
    
    p = multiprocessing.Process(target=f)
    p.start()
    
    while True:
        pass
    

    It checks what the process id is, and avoids calling the event loop if it is not the process id of the parent process.

    My guess is that you can not use the event loop in the other processes. It sounds like you can not use fork for the CoreFoundation stuff its using. Where multiprocess is using fork, and pygame is using particular CoreFoundation stuff that does not like fork. In short it does not look like an easy fix, so a work around might be needed.

    Depending on your program, perhaps using subprocess will work for you instead of multiprocess.

    There is a python bug here which talks about having an option to not use fork, and use exec instead, but I don't think it has landed yet: http://bugs.python.org/issue8713

    cheers,

  2. Mike Lawrence reporter

    René Dudfield: I'm a little confused; your code indeed avoids the crash I reported, but only because os.getpid() == parent_pid is never True and therefore pygame.event.pump() is never evaluated in the forked off process. My aim is to be able to draw in the main process while process inputs in the forked process.

  3. René Dudfield

    Hi,

    that is not going to work on OSX because CoreFoundation is used. Since CoreFoundation does not work with fork for this.

    You might need to use exec, or some other inter process communication. I know multiprocessing can use something like exec on windows instead of fork, but I'm not sure how to do it on OSX. Maybe someone more knowledgeable about multiprocessing will know.

  4. Log in to comment