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

[Bug or My fault about openfile, read, write] #2409

Closed
vicuna opened this issue Mar 29, 2000 · 2 comments
Closed

[Bug or My fault about openfile, read, write] #2409

vicuna opened this issue Mar 29, 2000 · 2 comments
Labels

Comments

@vicuna
Copy link

vicuna commented Mar 29, 2000

Original bug ID: 70
Reporter: administrator
Status: closed
Resolution: not a bug
Priority: normal
Severity: minor
Category: ~DO NOT USE (was: OCaml general)

Bug description

Hello

I have two problems with programming ocaml in linux.
I don't know exactly the problems are my faults or ocaml-bug.
So, now I'm writing this mail :)

Both two problems are related to openfile and file_perm.

The first problem is that file access right set by file_perm.
the new file does not have the same file permission which is setted
by file_perm.

I prepare the sample code.
(But when I run this code in Unix(Solaris), the problem doesn't occur,
so I feel dizzy)

There is k file. it have the simple contents, "Hello ~ "
and program read it, and make a copy (k2).

I absolutely use the openfile command with [O_RDWR; O_CREAT] 0o777
(rwxrwxrwx mode). but the created file has rwxrwxr-x
as using 0o775.

-------- here is code --------

open Unix
let read_size = ref 0
let rbuff = String.make 1024 ' '
let read_fd = openfile "/home/bskim/netPhone/ocaml_code/k" [O_RDWR] 0o777
let write_fd = openfile "/home/bskim/netPhone/ocaml_code/k2" [O_RDWR; O_CREAT] 0o777
let read_file () = let _ = read_size := read read_fd rbuff 0 1023 in ()
let write_file () = write write_fd rbuff 0 !read_size
let _ = ( read_file () ; write_file () )


testing
[bskim@plea ocaml_code]$ ls -la
total 349
drwxrwxr-x 2 bskim bskim 1024 3¿ù 29 17:38 ./
drwxrwxr-x 5 bskim bskim 1024 3¿ù 29 17:05 ../
-rw-rw-r-- 1 bskim bskim 121 3¿ù 29 17:05 Makefile
-rwxrwxr-x 1 bskim bskim 160802 3¿ù 29 17:27 a.out*
-rw-rw-r-- 1 bskim bskim 8 3¿ù 29 17:38 k
-rw-rw-r-- 1 bskim bskim 185452 3¿ù 29 17:05 p
-rw-rw-r-- 1 bskim bskim 860 3¿ù 29 17:27 p.cmi
-rw-rw-r-- 1 bskim bskim 716 3¿ù 29 17:27 p.cmo
-rw-rw-r-- 1 bskim bskim 400 3¿ù 29 17:27 p.ml
[bskim@plea ocaml_code]$ a.out
[bskim@plea ocaml_code]$ ls -la
total 350
drwxrwxr-x 2 bskim bskim 1024 3¿ù 29 17:40 ./
drwxrwxr-x 5 bskim bskim 1024 3¿ù 29 17:05 ../
-rw-rw-r-- 1 bskim bskim 121 3¿ù 29 17:05 Makefile
-rwxrwxr-x 1 bskim bskim 160802 3¿ù 29 17:27 a.out*
-rw-rw-r-- 1 bskim bskim 8 3¿ù 29 17:38 k
-rwxrwxr-x 1 bskim bskim 8 3¿ù 29 17:40 k2*
-rw-rw-r-- 1 bskim bskim 185452 3¿ù 29 17:05 p
-rw-rw-r-- 1 bskim bskim 860 3¿ù 29 17:27 p.cmi
-rw-rw-r-- 1 bskim bskim 716 3¿ù 29 17:27 p.cmo
-rw-rw-r-- 1 bskim bskim 400 3¿ù 29 17:27 p.ml


As you see the permission of k2 is rwxrwxr-x
Is this linux problem? or ocaml problem?

The second problem is openfile with the device "/dev/dsp" for recoding sound
and playback.
( The assumption is root change the permission of /dev/dsp to 666 )

I made program which records voice from microphone and plays back ASAP to
speaker with C-language and also make it with ocaml.

In ocaml-program, in order to configure the sound-card,
I used c codes which are the same as previous C-program's.

But whenever I run ocaml-program, the linux system is down and I always
have to reboot my PC.( real fatal error )

When I use only the recording part( read_audio () ) or
only use the play-back part(write_audio () ), the program terminates well.

Whenever I use both recording part and play-back part together,
the system is down.

I think ....
the second problem may be related to the first problem.
I attach my codes. Could you explain the reason?

regard..
Kenneth


main program in ocaml

    open Unix
    open Opendev
    (* Global Variable *)
    let sound_Device = "/dev/dsp"   (* audio device *)
    let sound_Format = 16           (* AFMT_S16_LE *)
    let sound_Rate = 8000
    let sound_Channels = 1          (* 1 : mono 2 : stereo *)
    let sound_Size = 1024           (* buffer size *)
    let sound_Frags = 3             (* 3 fragments *)
    let real_Frag = 196618          (* real Frag for SETFRAGMENT *)
    let dsp_fd = ref stderr         (* file descriptor default value *)

    let rbuff = String.make sound_Size ' ' (* buffer for recording *)

    let ip = ref 0                  (* ip for call *)

    let read_size = ref 0

    let open_sound_device ()  =     (* ip is not needed    *)
                                    (* settting sound card *)
    let
            (* open audio_device *)
            _ = dsp_fd := openfile sound_Device [O_RDWR] 0o777 in

            (* the setting order is important *)
            (* call functions defined in C language *) 
            let _ = setDuplex( !dsp_fd ) in
            let _ = setFragment  !dsp_fd real_Frag in
            let _ = setSamplesize !dsp_fd sound_Format in
            let _ = setChannels !dsp_fd sound_Channels in
            let actual_sampling = setSpeed !dsp_fd sound_Rate in
            let _ = print_string "Actual Sampling Frequency " in
            let _ = print_int actual_sampling in
            let _ = print_string "Hz\n" in
            let _ = flush Pervasives.stdout (* flush the buffer *) in
            let _ = samplePrint ()

    in
    (       print_string "end of open_sound_device \n"  ;
            flush Pervasives.stdout )


    let read_audio ()  =
    let
            _ = read_size := read !dsp_fd rbuff 0 1023
    in
            (!read_size)


    let write_audio () =
    let
            write_size = write !dsp_fd rbuff 0 (!read_size)
    in
            ()


    let rec get_voice () =
    if read_audio () > 0 then ( write_audio() ; get_voice () )
    else get_voice ()

    let main () = ( open_sound_device () ; get_voice () )


    let _ = main ()

opendev.mli

external setDuplex: Unix.file_descr -> unit = "setDuplex_C"
external setFragment: Unix.file_descr -> int -> unit = "setFragment_C"
external setSamplesize: Unix.file_descr -> int -> unit ="setSamplesize_C"
external setChannels: Unix.file_descr -> int -> unit ="setChannels_C"
external setSpeed: Unix.file_descr -> int -> int ="setSpeed_C"
external samplePrint: unit -> unit = "samplePrint_C"


opendev.c

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/soundcard.h>
#include <signal.h>

#include "/usr/local/lib/ocaml/caml/mlvalues.h"
#include <stdio.h>
value samplePrint_C( )
{

printf("Sample \n");
fflush( stdout ) ;
return Val_unit;
}

value setSpeed_C( value fd , value spd )
{
int fh = Int_val(fd) ;
int speed = Int_val(spd) ;
printf("Print Fild id %d \t Speed %d \n",fh,speed) ;
if (ioctl( fh, SNDCTL_DSP_SPEED, &speed) == -1 ) {
// fatal error
(void) printf("Error : Speed setting \n");
fflush( stdout ) ;
exit(-1) ;
}
return Val_int(speed) ;
}
value setChannels_C( value fd , value chan )
{
int fh = Int_val(fd) ;
int channels = Int_val(chan) ;
int CHANNEL = channels ;
printf("Print Fild id %d \t Chan %d \n",fh,channels) ;
fflush( stdout ) ;
if (ioctl( fh, SNDCTL_DSP_CHANNELS, &channels) == -1 ) {
// fatal error
(void) printf("Error : Channel setting \n") ;
fflush( stdout ) ;
exit(-1) ;
}
if ( channels != CHANNEL ){
(void) printf("Error : The device doesn't support the mode.\n");
fflush( stdout ) ;
exit(-1) ;
}
return Val_unit ;
}
value setSamplesize_C( value fd , value ssize )
{
int fh = Int_val(fd) ;
int format = Int_val(ssize) ;
printf("Print Fild id %d \t Format %d \n",fh,format) ;
fflush( stdout ) ;
ioctl(fh, SNDCTL_DSP_SAMPLESIZE, &format) ;
if( format != AFMT_S16_LE) {
printf("Error : Samplesize setting \n") ;
fflush( stdout ) ;
close(fh);
exit(-1);
}
return Val_unit ;
}
value setFragment_C( value fd , value frag )
{
int fh = Int_val(fd) ;
int real_frag = Int_val(frag) ;
printf("Print File id %d \t Real Frag %d \n",fh,real_frag);
fflush( stdout ) ;
//int real_frag = 196618 ;
//printf("Print Real Frag %d \n",real_frag);

if( ioctl( fh, SNDCTL_DSP_SETFRAGMENT, &real_frag) == -1 ){
printf("Error : Fragment setting \n");
fflush( stdout ) ;
close( fh) ;
exit(-1) ;
}
return Val_unit ;
}

value setDuplex_C( value fd )
{
int fh = Int_val(fd) ;
//printf("Passing the fd : %d\n", fh ) ;
if( ioctl( fh , SNDCTL_DSP_SETDUPLEX, 0) == -1 ){
printf("Error : Duplex setting \n") ;
fflush( stdout ) ;
close(fh);
exit(-1) ;
}
return Val_unit ;
}


same program in All C Language

// Unbuffered I/O

#define UNIX

#ifdef UNIX
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/soundcard.h>
#include <signal.h>
#endif UNIX

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

#define AUDIO_DEV "/dev/dsp"

#define BUFF_SIZE 1024 // 2^n size is better

#define CHANNEL 1 // 1 = mono, 2 = stereo

volatile int Signal_Was_Seen = 0 ;

// setting 3 sampling parameters
// sample format
// number of channels(mono or stero)
// sampling rate(speed)
// the order of setting is important

void signal_handler( int _sig){
Signal_Was_Seen = 1 ;
}
main()
{

int samplesize ;
int sound_dscrpt ;
int read_size ;
char buff[BUFF_SIZE] ;

// setting parameters
int format ; // sample format
int channels = CHANNEL ;
int speed = 8000 ;

// buffer size
int frag_size ;
int real_frag = 196618 ;
int real_caps;
// dealy
audio_buf_info ibuf;
audio_buf_info obuf;

// for malloc
short* ibuffer ;
void (*old_handler)(int);

sound_dscrpt = open(AUDIO_DEV, O_RDWR ) ;
if (sound_dscrpt < 0) {
(void) printf("Error : Unable to open %s \n",AUDIO_DEV) ;
exit(1) ;
}

// setting sampling parameters

if( ioctl( sound_dscrpt, SNDCTL_DSP_SETDUPLEX, 0 ) == -1 ) {
printf(" Duplex Error \n");
close( sound_dscrpt );
exit( -1 );
}

if( ioctl( sound_dscrpt , SNDCTL_DSP_SETFRAGMENT, &real_frag ) == -1 ) {
printf("SETFRAGMENT ERROR\n");
close( sound_dscrpt );
exit( -1 );
}

// 1. sample format
/* .voc files are 16 bit (now) */
samplesize = AFMT_S16_LE;
printf("Sample size : AFMT_S16_LE ==> %d \n", samplesize) ;

ioctl(sound_dscrpt, SNDCTL_DSP_SAMPLESIZE, &samplesize);
if (samplesize != AFMT_S16_LE) {
//fprintf(stderr, "%s: unable to set 16 bit sample size!\n", command);
printf("sample size \n");
exit (-1);
}

// 2. setting the number of channels (Mono/Stereo)
if (ioctl(sound_dscrpt, SNDCTL_DSP_CHANNELS, &channels) == -1 ) {
// fatal error
(void) printf("Error : SNDCTL_DSP_CHANNELS \n") ;
exit(1) ;

}
if ( channels != CHANNEL ){
(void) printf(" The device doesn't support the stereo mode.\n");
exit(1) ;
}

// 3. setting sampling rate (speed)
if (ioctl(sound_dscrpt, SNDCTL_DSP_SPEED, &speed) == -1 ) {
// fatal error
(void) printf("Error : SNDCTL_DSP_SPEED \n");
exit(1) ;
}

// change buffer size
if ( ioctl(sound_dscrpt, SNDCTL_DSP_GETBLKSIZE, &frag_size) == -1 ){
(void) printf("Error : Buffer Size \n") ;
exit(1) ;
}

(void) printf("Static fragment size( Recommened ) : %d \n", frag_size) ;

// read write with malloc
ibuffer = ( short* )malloc( 1 << 10 ) ;
if( !ibuffer ) {
fprintf( stderr, "Memory allocation Error.\n") ;
}

old_handler = signal(SIGINT, signal_handler) ;
do{
read_size = read( sound_dscrpt , buff , 1024) ;
(void) write( sound_dscrpt, buff , read_size ) ;

}while( !Signal_Was_Seen && read_size >0 ) ;

(void) close(sound_dscrpt) ;
return(0) ;

}


end of file

@vicuna
Copy link
Author

vicuna commented Mar 29, 2000

Comment author: administrator

The first problem is that file access right set by file_perm.
the new file does not have the same file permission which is setted
by file_perm.=20
I prepare the sample code.
(But when I run this code in Unix(Solaris), the problem doesn't occur,
so I feel dizzy)
There is k file. it have the simple contents, "Hello ~ "
and program read it, and make a copy (k2).
I absolutely use the openfile command with [O_RDWR; O_CREAT] 0o777
(rwxrwxrwx mode). but the created file has rwxrwxr-x
as using 0o775.

You'd observe the same behavior in a C program. This is a feature of
Unix: the mode you pass as third argument to "open" is AND-ed with the
complement of the current umask to determine the permissions of the
created file. Please do man 2 open and man 2 umask.

You can either change the umask in your program before calling
openfile (Unix.umask 0), or change the permissions after creating the file
(using Unix.chmod).

The second problem is openfile with the device "/dev/dsp" for
recoding soun= d and playback.
But whenever I run ocaml-program, the linux system is down and I always
have to reboot my PC.( real fatal error )=20

The most suspect thing I saw in your Caml code (besides lots of
useless references -- use "let" instead, that will be a lot clearer),
is the following:

    let read_audio ()  =3D
    let
            _ =3D read_size :=3D read !dsp_fd rbuff 0 1023
    in
            (!read_size)

Here you're reading by chunks of 1023 bytes, while in the C code
you're reading by chunks of 1024 bytes.

At any rate, even if a parameter to read() or write() isn't supported
by the driver, this shouldn't crash your computer. This is clearly a
bug in the Linux sound driver.

  • Xavier Leroy

@vicuna
Copy link
Author

vicuna commented Mar 29, 2000

Comment author: administrator

User's misunderstandings

@vicuna vicuna closed this as completed Mar 29, 2000
@vicuna vicuna added the bug label Mar 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant