2009-08-18 4 views
0

Этот код основан на splice-fromnet.c and splice-cp.c для сращивания от сокета к трубе и от трубы к файлу, но по какой-либо причине первый вызов сращивания никогда не возвращается.сращивание от розетки до трубы замороженное

static size_t splice_from_net_to_file(int infd, int outfd) 
{ 
    int p[2]; 
    size_t total = 0; 

    if (pipe(p) == -1) 
     return error("pipe"); 
    while (1) { 
     int ret; 
     ret = ssplice(infd, NULL, p[1], NULL, splice_size, 0); 

     if (ret < 0) { 
      close(p[0]); 
      close(p[1]); 
      return error("splice in pipe"); 
     } 
     else if (!ret) 
      break; 
     while (ret > 0) { 
      int written = ssplice(p[0], NULL, outfd, NULL, ret, 0); 
      if (written <= 0) { 
       close(p[0]); 
       close(p[1]); 
       return error("splice out pipe"); 
      } 
      ret -= written; 
      total += written; 
     }  
    } 
    close(p[0]); 
    close(p[1]); 
    return total; 
} 

Я тестировал это на linux 2.6.30.

ответ

1

Возможно ли, что вы не начали прослушивание на другой стороне трубы?

+0

Это было не так. Я думаю, что splice_size был слишком большим ... –

0

Где инициализируется splice_size?

+0

от splice-fromnet.c static unsigned int splice_size = SPLICE_SIZE; #define SPLICE_SIZE \t (64 * 1024) –

+0

Работает ли немодифицированный сплайс-кабель от сети в вашей системе? И код, основанный на нем, нарушен только? –

+0

Немодифицированная функция splice-fromnet работает нормально в моей системе. И да. –

0

Я думаю, что это блокирует, потому что на момент написания письма нет читателя на трубе. Вы должны уметь разрешить это, используя fork().

#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

static size_t splice_from_net_to_file(int infd, int outfd) 
{ 
    int p[2]; 
    pid_t fpid; 
    size_t total = 0; 

    if (pipe(p) == -1) 
     return error("pipe"); 

    fpid = fork(); 
    if (fpid == -1) 
     return error("fork"); 

    if (!fpid) /* child */ 
    { 
     int ret; 
     close(p[0]); /* don't need reading end */ 
     while ((ret = ssplice(infd, NULL, p[1], NULL, splice_size, 0)) > 0) 
      ; 
     close(p[1]); 
     if (ret < 0) 
     { 
      /* error("splice in pipe") */ 
      exit(-1); 
     } 
     exit(0); 
    } 
    else 
    { 
     /* parent */ 
     int ret; 
     close(p[1]); /* no need for writing end */ 
     while ((ret = ssplice(p[0], NULL, outfd, NULL, splice_size, 0)) > 0) 
      total += ret; 
     close(p[0]); 
     waitpid(fpid, NULL, 0); 

     if (ret < 0) 
     { 
      return error("splice out pipe"); 
     } 
    } 

    return total; 
} 
0

Я думаю, я просто столкнулся с этим - это из-за ошибки ядра, который был зафиксирован в 2.6.32 - см http://permalink.gmane.org/gmane.linux.network/138828 для деталей.

Существует обходной путь я нашел в http://git.samba.org/?p=samba.git;a=commitdiff;h=e1459a237948c2c9b7da94e4ba0acc79b1cd8eca - изменить первый стык() вызов из

ret = ssplice(infd, NULL, p[1], NULL, splice_size, 0); 

в

ret = ssplice(infd, NULL, p[1], NULL, MIN(splice_size, 16384), 0); 

так ограничить количество данных, которые вы просите.

Это заставляет меня работать для меня на 2.6.31.