SDL_Init() hangs with blank CDR (under linux)

Hi,

Yesterday I was trying to play frozen-bubble, but the game refused to
start. After a few tries I’ve understood that it was because of the
blank CDR in my cd burner! (in fact, frozen-bubble uses the sdl-perl
"SDL::App->new(…)", which uses “SDL_Init(SDL_INIT_EVERYTHING)”)

I’ve done a test with a very simple program:

#include <stdlib.h>
#include <SDL/SDL.h>

int main(int argc, char** argv)
{
SDL_Init(SDL_INIT_CDROM) ;
atexit(SDL_Quit) ;

SDL_Quit() ;
return(EXIT_SUCCESS) ;

}

Here is a partial strace of the execution:

<>
stat64("/dev/cdrom", {st_mode=S_IFBLK|0600, st_rdev=makedev(11, 0),
…}) = 0
open("/dev/cdrom", O_RDONLY|O_NONBLOCK|O_EXCL) = 3
ioctl(3, 0x530b

Here, the init process hangs, until I press the open button of the cdr
drive. It then continue:

ioctl(3, 0x530b, 0xbffff12c) = 0
close(3) = 0
<>
stat64("/dev/cdrw", {st_mode=S_IFBLK|0600, st_rdev=makedev(11,
0), …}) = 0
open("/dev/cdrw", O_RDONLY|O_NONBLOCK|O_EXCL) = 4
ioctl(4, 0x530b

Here it hangs again (/dev/cdrw and /dev/cdrom are the same device). I
again have to press the open button, and the the program can continue
and exit.

ioctl(4, 0x530b, 0xbffff07c) = -1 ENOMEDIUM (No medium found)
close(4) = 0
read(3, “”, 4096) = 0
close(3) = 0
<>

The workaround for this bug is quite simple: “don’t put a blank cdr in
the drive if you want to play to an sdl game.” But it can take a quite
long time to understand that the first time, so it would be nice if
somebody could fix that in libsdl.

Oh, and something else that may help:
I’m using Gentoo Linux, kernel 2.4.20-ck4, on a K7 PC.

Thanks for your all your work for the gamers community,–
Thomas.

Here is a partial strace of the execution:

<>
stat64("/dev/cdrom", {st_mode=S_IFBLK|0600, st_rdev=makedev(11, 0),
…}) = 0
open("/dev/cdrom", O_RDONLY|O_NONBLOCK|O_EXCL) = 3
ioctl(3, 0x530b

Here, the init process hangs, until I press the open button of the cdr
drive. It then continue:

Hmm, I’m not sure what to do about this. The CDROMSUBCHNL ioctl() is
used to determine whether the disk is indeed a CD-ROM drive. Does anybody
know another way that won’t hang with the Linux drivers? I assume that
the problem is the CD-ROM driver simply can’t find any track info and keeps
trying until interrupted…

See ya!
-Sam Lantinga, Software Engineer, Blizzard Entertainment

Sam Lantinga wrote:

Hmm, I’m not sure what to do about this. The CDROMSUBCHNL ioctl() is
used to determine whether the disk is indeed a CD-ROM drive. Does
anybody know another way that won’t hang with the Linux drivers?

Get the device file (hda, etc…) out of /etc/fstab or the current
mount table. For IDE devices, /proc/ide//media will contain
"cdrom" for CD and DVD devices.

For SCSI, you need to parse /proc/scsi/scsi. This requires some
knowlege (which I don’t have) of how the SCSI bus id’s map to device
files.

Both of these interfaces might change with kernel versions, of course.
But then so could the ioctl(). In all cases, reading files in proc is
safer, less opaque and less likely to cause driver trouble than
throwing ioctls at an open descriptor.

Andy–
Andrew J. Ross Beyond the Ordinary Plausibility Productions
Sole Proprietor Beneath the Infinite Hillsboro, OR
Experience… the Plausible?

Sam Lantinga wrote:

Hmm, I’m not sure what to do about this. The CDROMSUBCHNL ioctl() is
used to determine whether the disk is indeed a CD-ROM drive. Does
anybody know another way that won’t hang with the Linux drivers?

Get the device file (hda, etc…) out of /etc/fstab or the current
mount table. For IDE devices, /proc/ide//media will contain
"cdrom" for CD and DVD devices.

For SCSI, you need to parse /proc/scsi/scsi. This requires some
knowlege (which I don’t have) of how the SCSI bus id’s map to device
files.

Both of these interfaces might change with kernel versions, of course.
But then so could the ioctl(). In all cases, reading files in proc is
safer, less opaque and less likely to cause driver trouble than
throwing ioctls at an open descriptor.

I get program hangs (and even seg faults) when an SDL program tries
to init audio, and another program (typically xmms) has already
grabbed the sound card. Might that be caused by a similar problem?
The program in question uses SDL_Mixer, and the sound card in
question is a GUS.

Ron Steinke

“The sound of gunfire, off in the distance. I’m getting used to it now.”
– Talking Heads> From: Andy Ross

hrmm, i don’t seem to be able to reproduce the problem.
I wrote a test program to see what was going on when I tried to read a blank
cdr, and it just reports the tray as being empty.
here 's the code i used, taken mainly from the sdl documentation

#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>

int main()
{
SDL_CD *cdrom;
int cur_track;
int min, sec, frame;
int numDrives;
int openMe;
CDstatus status;

/* init & quit section /
SDL_Init(SDL_INIT_CDROM);
atexit(SDL_Quit);
/
end init & quit */

/* Check for CD drives /
if((numDrives = SDL_CDNumDrives()) == 0){
/
None found */
fprintf(stderr, “No CDROM devices available\n”);
exit(-1);
}
fprintf(stdout, “Number of CDROM devices found: %d\n”,numDrives);

fprintf(stdout,"\n\tPlease enter the drive number you wish to open: “);
scanf(”%d",&openMe);
if(openMe < 0 || openMe > numDrives)
{
fprintf(stderr, “Not a valid drive number, bu-bye.\n”);
exit(-1);
}

/* Open the default drive */
cdrom=SDL_CDOpen(openMe);

/* Did if open? Check if cdrom is NULL */
if(!cdrom){
fprintf(stderr, “Couldn’t open drive: %s\n”, SDL_GetError());
exit(-1);
}

status = SDL_CDStatus(cdrom);
switch(status)
{
case CD_TRAYEMPTY:
fprintf(stdout, “CD Tray is empty.\n”);
exit(1);
break;
case CD_STOPPED:
fprintf(stdout, “CD is stopped.\n”);
break;
case CD_PLAYING:
fprintf(stdout, “CD is playing. \n”);
break;
case CD_PAUSED:
fprintf(stdout, “CD is paused.\n”);
break;
case CD_ERROR:
fprintf(stdout, “<GRKK!> CD ERROR. \n”);
exit(1);
break;
default:
fprintf(stdout,"<Ack!> Unknown Error…\n\tmust…be…\nUSER
SURLEY!\n");
exit(-1);
break;
} /* end switch(status) */

/* Print Volume info */
printf(“Name: %s\n”, SDL_CDName(openMe));
printf(“Tracks: %d\n”, cdrom->numtracks);
for(cur_track=0;cur_track < cdrom->numtracks; cur_track++)
{
FRAMES_TO_MSF(cdrom->track[cur_track].length, &min, &sec, &frame);
printf("\tTrack %d: Length %d:%d\n", cur_track, min, sec);
}

SDL_CDClose(cdrom);

return 0;
}On Friday 07 March 2003 12:55 am, Sam Lantinga wrote:

Here is a partial strace of the execution:

<>
stat64("/dev/cdrom", {st_mode=S_IFBLK|0600, st_rdev=makedev(11, 0),
…}) = 0
open("/dev/cdrom", O_RDONLY|O_NONBLOCK|O_EXCL) = 3
ioctl(3, 0x530b

Here, the init process hangs, until I press the open button of the cdr
drive. It then continue:

Hmm, I’m not sure what to do about this. The CDROMSUBCHNL ioctl() is
used to determine whether the disk is indeed a CD-ROM drive. Does anybody
know another way that won’t hang with the Linux drivers? I assume that
the problem is the CD-ROM driver simply can’t find any track info and keeps
trying until interrupted…

See ya!
-Sam Lantinga, Software Engineer, Blizzard Entertainment


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Sam Lantinga wrote:

Hmm, I’m not sure what to do about this. The CDROMSUBCHNL ioctl() is
used to determine whether the disk is indeed a CD-ROM drive. Does anybody
know another way that won’t hang with the Linux drivers? I assume that
the problem is the CD-ROM driver simply can’t find any track info and keeps
trying until interrupted…

is there anyway to put a timeout on it?