pike.git / src / modules / Pipe / pipe.c

version» Context lines:

pike.git/src/modules/Pipe/pipe.c:12:   #include "stralloc.h"   #include "pike_macros.h"   #include "object.h"   #include "constants.h"   #include "interpret.h"   #include "svalue.h"   #include "pike_error.h"   #include "builtin_functions.h"   #include "fdlib.h"    - #include <sys/types.h> +    #include <sys/stat.h>      #ifdef HAVE_SYS_FILE_H   #include <sys/file.h>   #endif /* HAVE_SYS_FILE_H */      #include <errno.h>      /* Some <sys/mman.h>'s (eg AIX 5L/ia64) contain a #define of MAP_VARIABLE    * for use as the opposite of MAP_FIXED.
pike.git/src/modules/Pipe/pipe.c:108:   #define MAX_BYTES_IN_BUFFER 65536      /*! @module Pipe    *!    *! Single socket output.    *!    *! Regular file output and (multiple, adding) socket output    *! with no mmap input.    *!    *! Multiple socket output without regular file output illegal. +  *! +  *! @note +  *! It is preferable to use the @[Shuffler] API, it is significantly +  *! more flexible.    */      static struct program *pipe_program, *output_program;      #ifdef THIS   #undef THIS   #endif   #define THIS ((struct pipe *)(Pike_fp->current_storage))   #define THISOBJ (Pike_fp->current_object)   
pike.git/src/modules/Pipe/pipe.c:206:   static INLINE void output_finish(struct object *obj);   static INLINE void output_try_write_some(struct object *obj);      /********** internal ********************************************************/      /* Push a callback to this object given the internal function number.    */   static void push_callback(ptrdiff_t no)   {    SET_SVAL(*Pike_sp, T_FUNCTION, -  DO_NOT_WARN(no + Pike_fp->context->identifier_level), +  no + Pike_fp->context->identifier_level,    object, THISOBJ);    add_ref(THISOBJ);    Pike_sp++;   }      /* Allocate a new struct input, link it last in the linked list */   static INLINE struct input *new_input(void)   {    struct input *i;    ninputs++;
pike.git/src/modules/Pipe/pipe.c:270: Inside #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
  #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)    munmap(i->u.mmap,i->len);    mmapped -= i->len;   #else    Pike_error("I_MMAP input when MMAP is diabled!");   #endif    break;       case I_NONE: break;    } -  free((char *)i); +  free(i);   }      /* do the done_callback, then close and free everything */   static INLINE void pipe_done(void)   {    if (TYPEOF(THIS->done_callback) != T_INT)    {    assign_svalue_no_free(sp++,&THIS->id);    apply_svalue(&(THIS->done_callback),1);    pop_stack();
pike.git/src/modules/Pipe/pipe.c:321:    struct buffer *b;       debug_malloc_touch(s);       if(THIS->fd!= -1)    {    ptrdiff_t len = s->len;    char *data = s->str;    ptrdiff_t bytes;    -  fd_lseek(THIS->fd, THIS->pos, SEEK_SET); +  while ((fd_lseek(THIS->fd, THIS->pos, SEEK_SET) < 0) && (errno == EINTR)) +  ;    while (len > 0) {    do {    bytes = fd_write(THIS->fd, data, len);    } while ((bytes < 0) && (errno == EINTR));    if (bytes < 0) break;    data += bytes;    len -= bytes;    }    THIS->pos+=s->len;    return 0;
pike.git/src/modules/Pipe/pipe.c:400:   /* Read some data from the blocking object.    *    */   static int read_some_data(void)   {    struct pipe *this = THIS;    struct input * i = this->firstinput;       if (!i || i->type != I_BLOCKING_OBJ) {    Pike_fatal("PIPE: read_some_data(): Bad input type!\n"); -  return -1; +  UNREACHABLE(return -1);    }    push_int(8192);    push_int(1); /* We don't care if we don't get all 8192 bytes. */    apply(i->u.obj, "read", 2);    if ((TYPEOF(sp[-1]) == T_STRING) && (sp[-1].u.string->len > 0)) {    append_buffer(sp[-1].u.string);    pop_stack();    THIS->sleeping = 1;    return(1); /* Success */    }
pike.git/src/modules/Pipe/pipe.c:484:       /* We have a file cache, read from it */    if (this->fd!=-1)    {    char buffer[READ_BUFFER_SIZE];    ptrdiff_t sz = this->pos-pos;       if (sz <= 0) return NULL; /* no data */    if (sz > READ_BUFFER_SIZE) sz = READ_BUFFER_SIZE;    THREADS_ALLOW(); -  fd_lseek(this->fd, pos, SEEK_SET); +  while ((fd_lseek(this->fd, pos, SEEK_SET) < 0) && (errno == EINTR)) +  ;    THREADS_DISALLOW();    do {    THREADS_ALLOW();    len = fd_read(this->fd, buffer, sz);    THREADS_DISALLOW();    if (len < 0) {    if (errno != EINTR) {    return(NULL);    }    check_threads_etc();
pike.git/src/modules/Pipe/pipe.c:519:    /* Free the first buffer, and update THIS->pos */    b=this->firstbuffer;    this->pos+=b->s->len;    this->bytes_in_buffer-=b->s->len;    this->firstbuffer=b->next;    if (!b->next)    this->lastbuffer=NULL;    sbuffers-=b->s->len;    nbuffers--;    free_string(b->s); -  free((char *)b); +  free(b);       /* Wake up first input if it was sleeping and we    * have room for more in the buffer.    */    if (this->sleeping &&    this->firstinput &&    this->bytes_in_buffer<MAX_BYTES_IN_BUFFER)    {    if (this->firstinput->type == I_BLOCKING_OBJ) {    if (!read_some_data()) {
pike.git/src/modules/Pipe/pipe.c:566: Inside #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
   this->pos += this->firstinput->len;    input_finish();    continue;    }    len = this->firstinput->len + this->pos - pos;    if (len > READ_BUFFER_SIZE) len=READ_BUFFER_SIZE;    tmp = begin_shared_string( len );    src = this->firstinput->u.mmap + pos - this->pos;   /* This thread_allow/deny is at the cost of one extra memory copy */    THREADS_ALLOW(); -  MEMCPY(tmp->str, src, len); +  memcpy(tmp->str, src, len);    THREADS_DISALLOW();    return end_shared_string(tmp);    }    else   #endif    if (this->firstinput->type!=I_OBJ)    {    /* FIXME: What about I_BLOCKING_OBJ? */    input_finish(); /* shouldn't be anything else ... maybe a finished object */    }
pike.git/src/modules/Pipe/pipe.c:747: Inside #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
      apply(obj, "query_fd", 0);    if(TYPEOF(sp[-1]) == T_INT) fd=sp[-1].u.integer;    pop_stack();       if (fd != -1 && fstat(fd,&s)==0)    {    off_t filep=fd_lseek(fd, 0L, SEEK_CUR); /* keep the file pointer */    size_t len = s.st_size - filep;    if(S_ISREG(s.st_mode) /* regular file */ +  && (filep >= 0) /* lseek() succeeded. */    && ((m=(char *)mmap(0, len, PROT_READ,    MAP_FILE|MAP_SHARED,fd,filep))+1))    {    mmapped += len;       i->type=I_MMAP;    i->len = len;    i->u.mmap=m;   #if defined(HAVE_MADVISE) && defined(MADV_SEQUENTIAL)    /* Mark the pages as sequential read only access... */    madvise(m, len, MADV_SEQUENTIAL);   #endif -  pop_n_elems(args); -  push_int(0); +     return;    }    }    }   #endif       i->u.obj=obj;    nobjects++;    i->type=I_OBJ;    add_ref(i->u.obj);
pike.git/src/modules/Pipe/pipe.c:806:    return;    }    }       if (i==THIS->firstinput)    {    push_callback(offset_input_read_callback);    push_int(0);    push_callback(offset_input_close_callback);    apply_low(i->u.obj,i->set_nonblocking_offset,3); -  pop_stack(); +     }    else    {    /* DOESN'T WORK!!! */    push_int(0);    push_int(0);    push_callback(offset_input_close_callback);    apply_low(i->u.obj,i->set_nonblocking_offset,3); -  pop_stack(); +     } -  -  pop_n_elems(args); -  push_int(0); +    }      /*! @decl void write(string bytes)    *!    *! Add an input string to this pipe.    */   static void pipe_write(INT32 args)   {    struct input *i;   
pike.git/src/modules/Pipe/pipe.c:894:    THIS->pos=fd_lseek(fd, 0L, SEEK_CUR);       THIS->living_outputs++;       while (THIS->firstbuffer)    {    ptrdiff_t len;    char *data;    b=THIS->firstbuffer;    THIS->firstbuffer=b->next; -  fd_lseek(THIS->fd, THIS->pos, SEEK_SET); +  while ((fd_lseek(THIS->fd, THIS->pos, SEEK_SET) < 0) && +  (errno == EINTR)) +  ;       len = b->s->len;    data = b->s->str;    while (len > 0) {    ptrdiff_t bytes;    do {    bytes = fd_write(THIS->fd, data, len);    } while((bytes < 0) && (errno == EINTR));    if (bytes < 0) break;    len -= bytes;    data += bytes;    }       sbuffers-=b->s->len;    nbuffers--;    free_string(b->s); -  free((char *)b); +  free(b);    }    THIS->lastbuffer=NULL;       /* keep the file pointer of the duped fd    THIS->pos=0; */    push_int(0);    apply(sp[-args-2].u.object,"set_id", 1); -  pop_n_elems(args+2); /* ... and from apply x 2 */ +     return;    }    pop_stack(); /* from apply */    }       THIS->living_outputs++;    /* add_ref(THISOBJ); */ /* Weird */       /* Allocate a new struct output */    obj=clone_object(output_program,0);
pike.git/src/modules/Pipe/pipe.c:971:    o->pos=THIS->pos;       push_object(obj); /* Ok, David, this is probably correct, but I dare you to explain why :) */    apply(o->obj,"set_id",1);    pop_stack();       push_int(0);    push_callback(offset_output_write_callback);    push_callback(offset_output_close_callback);    apply_low(o->obj,o->set_nonblocking_offset,3); -  pop_stack(); -  -  pop_n_elems(args-1); +    }      /*! @decl void set_done_callback(void|function(mixed:mixed) done_cb, @    *! void|mixed id)    *!    *! Set the callback function to be called when all the outputs    *! have been sent.    */   static void pipe_set_done_callback(INT32 args)   {
pike.git/src/modules/Pipe/pipe.c:1002:    Pike_error("Illegal argument to set_done_callback()\n");       if (args>1)    {    free_svalue(&THIS->id);    assign_svalue_no_free(&(THIS->id),sp-args+1);    }       free_svalue(&THIS->done_callback);    assign_svalue_no_free(&(THIS->done_callback),sp-args); -  pop_n_elems(args-1); +    }      /*! @decl void set_output_closed_callback(void|function(mixed, object:mixed) close_cb, @    *! void|mixed id)    *!    *! Set the callback function to be called when one of the outputs has    *! been closed from the other side.    */   static void pipe_set_output_closed_callback(INT32 args)   {
pike.git/src/modules/Pipe/pipe.c:1030:    TYPEOF(sp[-args]) != T_ARRAY))    Pike_error("Illegal argument to set_output_closed_callback()\n");       if (args>1)    {    free_svalue(&THIS->id);    assign_svalue_no_free(&(THIS->id),sp-args+1);    }    free_svalue(&THIS->output_closed_callback);    assign_svalue_no_free(&(THIS->output_closed_callback),sp-args); -  pop_n_elems(args-1); +    }      /*! @decl void finish()    *!    *! Terminate and reinitialize the pipe.    */ - static void pipe_finish(INT32 args) + static void pipe_finish(INT32 UNUSED(args))   { -  pop_n_elems(args); -  push_int(0); +     pipe_done();   }      /*! @decl void start()    *!    *! Start sending the input(s) to the output(s).    */ - static void pipe_start(INT32 args) /* force start */ + static void pipe_start(INT32 UNUSED(args)) /* force start */   {    low_start(); -  if(args) -  pop_n_elems(args-1); +    }      /*! @decl int bytes_sent()    *!    *! Return the number of bytes sent.    */   static void f_bytes_sent(INT32 args)   {    pop_n_elems(args);    push_int(THIS->sent);
pike.git/src/modules/Pipe/pipe.c:1079:    if (args<1 || TYPEOF(sp[-args]) != T_OBJECT)    Pike_error("Illegal argument to pipe->write_output_callback\n");       if(!sp[-args].u.object->prog) return;       if(sp[-args].u.object->prog != output_program)    Pike_error("Illegal argument to pipe->write_output_callback\n");       debug_malloc_touch(sp[-args].u.object);    output_try_write_some(sp[-args].u.object); -  pop_n_elems(args-1); +    }      static void pipe_close_output_callback(INT32 args)   {    struct output *o;    if (args<1 || TYPEOF(sp[-args]) != T_OBJECT)       if(!sp[-args].u.object->prog) return;       if(sp[-args].u.object->prog != output_program)
pike.git/src/modules/Pipe/pipe.c:1103:       if (TYPEOF(THIS->output_closed_callback) != T_INT)    {    assign_svalue_no_free(sp++,&THIS->id);    push_object(o->obj);    apply_svalue(&(THIS->output_closed_callback),2);    pop_stack();    }       output_finish(sp[-args].u.object); -  pop_n_elems(args-1); +    }      static void pipe_read_input_callback(INT32 args)   {    struct input *i;    struct pike_string *s;       if (args<2 || TYPEOF(sp[1-args]) != T_STRING)    Pike_error("Illegal argument to pipe->read_input_callback\n");   
pike.git/src/modules/Pipe/pipe.c:1133:    /* THIS DOES NOT WORK */    push_int(0);    push_int(0);    push_callback(offset_input_close_callback);    apply_low(i->u.obj,i->set_nonblocking_offset,3);    pop_stack();    THIS->sleeping=1;    }       low_start(); -  pop_n_elems(args-1); +    }    - static void pipe_close_input_callback(INT32 args) + static void pipe_close_input_callback(INT32 UNUSED(args))   {    struct input *i;    i=THIS->firstinput;       if(!i)    Pike_error("Input close callback without inputs!\n");       if(i->type != I_OBJ)    Pike_error("Premature close callback on pipe!.\n");   
pike.git/src/modules/Pipe/pipe.c:1161:    pop_stack();   #endif    apply(i->u.obj,"close",0);    pop_stack();    }    nobjects--;    free_object(i->u.obj);    i->type=I_NONE;       input_finish(); -  if(args) -  pop_n_elems(args-1); +    }      /*! @decl string version()    *!    *! Return the version of the module.    */   static void pipe_version(INT32 args)   {    pop_n_elems(args); -  push_text("PIPE ver 2.0"); +  push_static_text("PIPE ver 2.0");   }      /********** init/exit *******************************************************/      void close_and_free_everything(struct object *thisobj,struct pipe *p)   {    struct buffer *b;    struct input *i;    struct output *o;    struct object *obj;
pike.git/src/modules/Pipe/pipe.c:1203:    add_ref(thisobj); /* don't kill object during this */       while (p->firstbuffer)    {    b=p->firstbuffer;    p->firstbuffer=b->next;    sbuffers-=b->s->len;    nbuffers--;    free_string(b->s);    b->next=NULL; -  free((char *)b); /* Hubbe */ +  free(b); /* Hubbe */    }    p->lastbuffer=NULL;          while (p->firstinput)    {    i=p->firstinput;    p->firstinput=i->next;    free_input(i);    }
pike.git/src/modules/Pipe/pipe.c:1246:    free_svalue(& p->output_closed_callback);    free_svalue(& p->id);       SET_SVAL_TYPE(p->done_callback, T_INT);    SET_SVAL_TYPE(p->output_closed_callback, T_INT);    SET_SVAL_TYPE(p->id, T_INT);       /* p->done=0; */   }    - static void init_pipe_struct(struct object *o) + static void init_pipe_struct(struct object *DMALLOCUSED(o))   {    debug_malloc_touch(o);       THIS->firstbuffer=THIS->lastbuffer=NULL;    THIS->firstinput=THIS->lastinput=NULL;    THIS->firstoutput=NULL;    THIS->bytes_in_buffer=0;    THIS->pos=0;    THIS->sleeping=0;    THIS->done=0;    THIS->fd=-1;    SET_SVAL_TYPE(THIS->done_callback, T_INT);    SET_SVAL_TYPE(THIS->output_closed_callback, T_INT);    SET_SVAL_TYPE(THIS->id, T_INT);    THIS->id.u.integer=0;    THIS->living_outputs=0;    THIS->sent=0;   }    - static void exit_pipe_struct(struct object *o) + static void exit_pipe_struct(struct object *UNUSED(o))   {    close_and_free_everything(NULL,THIS);   }    - static void exit_output_struct(struct object *obj) + static void exit_output_struct(struct object *DMALLOCUSED(obj))   {    struct output *o;       debug_malloc_touch(obj);    o=(struct output *)(Pike_fp->current_storage);       if (o->obj)    {    if(o->obj->prog)    {
pike.git/src/modules/Pipe/pipe.c:1303:    if(!THISOBJ->prog)    Pike_error("Pipe done callback destructed pipe.\n");    }    free_object(o->obj);    noutputs--;    o->obj=0;    o->fd=-1;    }   }    - static void init_output_struct(struct object *ob) + static void init_output_struct(struct object *DMALLOCUSED(ob))   {    struct output *o;    debug_malloc_touch(ob);    o=(struct output *)(Pike_fp->current_storage);    o->obj=0;   }         /********** Pike init *******************************************************/      void port_setup_program(void);      void f__pipe_debug(INT32 args)   {    pop_n_elems(args); -  push_int(DO_NOT_WARN(noutputs)); -  push_int(DO_NOT_WARN(ninputs)); -  push_int(DO_NOT_WARN(nstrings)); -  push_int(DO_NOT_WARN(nobjects)); -  push_int(DO_NOT_WARN(mmapped)); -  push_int(DO_NOT_WARN(nbuffers)); -  push_int(DO_NOT_WARN(sbuffers)); +  push_int(noutputs); +  push_int(ninputs); +  push_int(nstrings); +  push_int(nobjects); +  push_int(mmapped); +  push_int(nbuffers); +  push_int(sbuffers);    f_aggregate(7);   }      /*! @endclass    */      /*! @endmodule    */      PIKE_MODULE_INIT