[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[pygame] BUG:? pygame.mixer.music crash



Problem:

pygame.mixer.music crash while changing song

pygame versions with problems:

1.7.1 : got from pygame site maybe two years ago, the binary dependencies at same time , the binaries readme tells it is SDL - 1.2.7 , with SDL_mixer - 1.2.3, built with MSVC 6. Lots of pygame games run with no problems.

1.8.1.rc3 : test 1 both with the telus build and the 'automated build', tests 2 and 3 only tested against telus build

Other info:
winXP + sp2, python 2.4.3, integrated audio nvidia nforce2, audio drivers version 5.10.2917.0
Tested on more than a single machine, but same hardware.

Problem - bugdemos history:

1. I am one of the magicor (http://magicor.sourceforge.net) developers, working in windows; with pygame 1.7.1 no real problems with the game, but trying the pygame 1.8.1.rc3 crashes begin.
I tracked the problem to the moment pygame.mixer.music is instructed to change the current song.
The crash is a GPF, not even a 'pygame parachute', and the OS tell the fault is at sdl_mixer.dll , vs 1.2.8.0 ( provided with the windows installer for pygame 1.8.1.rc3 )
The specific fail moment is when in the levelselect menu the user gives an 'esc', wich normally will change to the main menu.
I tryied with both the telus build and the 'automated build', same problem.
1.8.1.rc3 installed after unistall 1.7.1 and deleting the remaining site-packages\pygame dir

 

2. Then I wrote mtest2.py (atached) to demo the problem in short code; it responds to keypresess changing or restarting the song played.
( to try it you must get two songs from the magicor repo, data\music\menu.xm and data\levels\egypt\egyptian-trance.xm )
All right, at first seemed to worked as expected: no fail in 1.7.1, fail in 1.8.1.rc3. 
With more runs, they start to appear crashes in 1.7.1, albeit mostly 'pygame parachute's.
Failures not so consistent. Maybe sensitive to the timming of keypresses, sometimes closing a console and starting other seems to help to get failures.
Restarting ( keypress 'r' ) seems more prone to crash than toggle song ( keypress 't' ) in pygame 1.7.1, the other way with 1.8.1.rc3
the song 'egyptian-trance.xm' seems to crash more than menu.xm ( in repeat mode )
Two or tree toggles in 1.8.1.rc3 usually suffice to crash, 1.7.1 seems les prone to crash.

3. To have a better testbed for posible workarounds, I wrote a test that colects some stats.
trunner2.py (the test runner) and ,mtest4.py ( the test ) - both atached.

trunner2 will run k-times mtest4.py as a subprocess, counting the crashes.
mtest4.py is an automated mtest2.py, it attempts to do a programable count of song changes, be it by restarting the same sound or changing to the other. If not crashed, will add a line to a log file. ( Note: that works well with 1.7.1, but in 1.8.1.rc3 you must close manually the OS messagebox that informs about the gpf )
Finally trunner will report the stats.

That was better, but I suspect the test is introducing some artifacts. Specifically, the failure ratio for 1.7.1 seems too high ( 22/25 , 24/25 for song 'egyptian-trance.xm , 12/25 for 'menu.xm', change_mode as restart same song ). And seems that if run k fails then run k+1 probably will fail. Suspecting an OS cleanup after crash can interfere, I added a litle wait between test runs, thats the time_sleep in trunner2.py . With it, failures goes down to 1/25 , 0/25 , more reasonable in the light that magicor doenst crash with 1.7.1


Some results:

---
Trunner2 results wwith pygame 1.7.1
run1:
initial song: 1
change mode is toggle: 1
time_sleep: None
runs: 25
changes per runs: 10
success: 3
failed: 22

run2:
initial song: 1
change mode is toggle: 1
time_sleep: 0.5
runs: 25
changes per runs: 10
success: 25
failed: 0

initial song: 1
change mode is toggle: 0
time_sleep: 0.5
runs: 25
changes per runs: 10
success: 25
failed: 0

initial song: 1
change mode is toggle: 0
time_sleep: None
runs: 25
changes per runs: 10
success: 3
failed: 22

------------
Trunner2 results wwith pygame 1.8.1.rc3
initial song: 1
change mode is toggle: 1
time_sleep: None
runs: 25
changes per runs: 10
success: 0
failed: 25

initial song: 1
change mode is toggle: 1
time_sleep: 0.5
runs: 25
changes per runs: 10
success: 0
failed: 25

initial song: 1
change mode is toggle: 0
time_sleep: 0.5
runs: 25
changes per runs: 10
success: 25
failed: 0

-------------

Allright, I will try to build some workaround and report.
If there is some sugestion from the pygame builders I will be glad to test.
Be patient with the mail, Im working out of town and checking mail at a cybercafe once a day.

--
claxo

import subprocess, time

# params test run
maxruns = 25
ch_per_run = 10

# 
bToggle = 0
initial_song = 1
time_sleep = None # use None for no sleep beetwen runs

cntruns = 0
cntfailed = 0

#clean stats
f = open('tstats.txt','w')
f.write('Start.\n')
f.close()

sl = ['python.exe','mtest4.py','%d'%ch_per_run,'%d'%bToggle,'%d'%initial_song ]
for i in xrange(maxruns):
    cntruns +=1 
    ret = subprocess.call(sl)
    if time_sleep:
        time.sleep(time_sleep)
        
f = open('tstats.txt','r')
cntsucces = len(f.readlines())-1
f.close()
print 'initial song:',initial_song
print 'change mode is toggle:',bToggle
print 'time_sleep:',time_sleep
print 'runs:', maxruns
print 'changes per runs:',ch_per_run
print 'success:',cntsucces
print 'failed:', maxruns-cntsucces
    
#mejorar las estadisticas contando nre de changes exitosos, incluyendo los de
#runs incompletas.
import pygame
import pygame.mixer
import sys, time
import subprocess

#self.music = music #? conflict with pygame.mixer.music ? # en/dis

##key1 : togle song
##key2 : reload same song
##key3 : quit

def play_music( song, musicVol ):
    print 'About to start song:',song
    pygame.mixer.music.set_volume(musicVol*0.01)
    pygame.mixer.music.load( song )
    pygame.mixer.music.play(-1) # looped

def stop_music():
    if pygame.mixer.get_init():
        pygame.mixer.music.stop()

ch_per_run = 0
try:
    ch_per_run = int(sys.argv[1])
    bToggle = int(sys.argv[2])
    selected = int(sys.argv[3])
except:
    pass

if ch_per_run<1:
    print """
    Usage:
    \tmtest3.py  n  b  s  
    Where:
    \tn > 1 Number of changes to try
    \tb = 0-1 1->toggle songs, 0->restart song
    \ts = 0-1 starting song, 0->menu.xm , 1->egyptian-trance.xm 
    """
    sys.exit(1)
    
    

pygame.display.init()
pygame.mixer.init(44100, -16, True, 4096)
pygame.mixer.set_num_channels(8)

soundVol = 100
musicVol = 100
songs = ['menu.xm', 'egyptian-trance.xm']

chtime = time.time()+1.0
play_music( songs[selected], musicVol)
if bToggle:
    selected = not selected

pygame.display.set_mode((300,300))
screen = pygame.display.get_surface()
screen.fill((0,0,255))
clock = pygame.time.Clock()

cntChanges = 0
bContinue = True
while bContinue:
#    pygame.event.pump()
    for ev in pygame.event.get():
        if (ev.type == pygame.KEYDOWN):
            if ev.key == pygame.K_ESCAPE:
                bContinue = False
    if time.time()>chtime:
        chtime = time.time() + 1.0
        play_music( songs[selected], musicVol)
        if bToggle:
            selected = not selected
        cntChanges += 1
        if cntChanges > ch_per_run:
            bContinue = False
    pygame.display.update()
    clock.tick(25)
                            
pygame.quit()             

f = open('tstats.txt','a')
f.write('run completed\n')
f.close()
sys.exit(7)


# En r hizo pygame_parachute:
# Fatal Python error: (pygame parachute) Segmentation Fault

#tambien en t, pero no siempre.

# agregando un stop_music antes de music.load() se fue la falla en pygame 1.7.1

# cambiando music por pygame.mixer.music en 1.7.1 parece que no cuelga.
# pero en 1.8.1.rc3 si cuelga.

# En 1.8.1.rc1 no es totalmente repetible; ademas a veces lo hace con togglr, no
# necesariamente con restart. Pero no hace parachute; es directamente gpf

# Adicionalmente podriamos probar si quitando el music.play() [ que parece
# redundante ] hay cuelgue o no -> no era redundante; el nuevo file no empieza a tocar.

# probando sin play y sin stop
import pygame
import pygame.mixer
#from pygame.mixer import music


#self.music = music #? conflict with pygame.mixer.music ? # en/dis

##key1 : togle song
##key2 : reload same song
##key3 : quit

def play_music( song, musicVol ):
    #stop_music() #@ cures the crash
    print 'About to start song:',song
    pygame.mixer.music.set_volume(musicVol*0.01)
    pygame.mixer.music.load( song )
    pygame.mixer.music.play(-1) # looped

def stop_music():
    if pygame.mixer.get_init():
        pygame.mixer.music.stop()

pygame.display.init()
pygame.mixer.init(44100, -16, True, 4096)
pygame.mixer.set_num_channels(8)

soundVol = 100
musicVol = 100
songs = ['menu.xm', 'egyptian-trance.xm']
selected = 0

print """
\nUse:
\t t: toggle song
\t r: restart song
\t esc: quit
"""
pygame.display.set_mode((300,300))
screen = pygame.display.get_surface()
screen.fill((0,0,255))
clock = pygame.time.Clock()

bContinue = True
while bContinue:
#    pygame.event.pump()
    for ev in pygame.event.get():
        if (ev.type == pygame.KEYDOWN):
            if ev.key == pygame.K_ESCAPE:
                bContinue = False
            elif ev.key == pygame.K_t:
                selected = not selected
                play_music( songs[selected], musicVol)
            elif ev.key == pygame.K_r:
                play_music( songs[selected], musicVol)
            else:
                pass
        pygame.display.update()
        clock.tick(25)
                            
pygame.quit()             

# En r hizo pygame_parachute:
# Fatal Python error: (pygame parachute) Segmentation Fault

#tambien en t, pero no siempre.

# agregando un stop_music antes de music.load() se fue la falla en pygame 1.7.1

# cambiando music por pygame.mixer.music en 1.7.1 parece que no cuelga.
# pero en 1.8.1.rc3 si cuelga.

# En 1.8.1.rc1 no es totalmente repetible; ademas a veces lo hace con togglr, no
# necesariamente con restart. Pero no hace parachute; es directamente gpf

# Adicionalmente podriamos probar si quitando el music.play() [ que parece
# redundante ] hay cuelgue o no -> no era redundante; el nuevo file no empieza a tocar.

# probando sin play y sin stop