Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0000070OCamlOCaml generalpublic2000-03-29 23:242000-03-29 17:34
Reporteradministrator 
Assigned To 
PrioritynormalSeverityminorReproducibilityalways
StatusclosedResolutionno change required 
PlatformOSOS Version
Product Version 
Target VersionFixed in Version 
Summary0000070: [Bug or My fault about openfile, read, write]
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.

1.
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


TagsNo tags attached.
Attached Files

- Relationships

-  Notes
(0002094)
administrator (administrator)
2000-03-29 17:33

> 1.
> 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

(0002095)
administrator (administrator)
2000-03-29 17:34

User's misunderstandings

- Issue History
Date Modified Username Field Change
2005-11-18 10:13 administrator New Issue


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker