2013-12-20 8 views
0

Я получаю ошибку Broken Pipe при записи большого количества данных очень быстро в подпроцесс C.Подпроцесс C из Python: sub.stdin.write IOError Broken Pipe

Так я бегу переменного тока подпроцесс из питона сценария:

process = subprocess.Popen("./gpiopwm", stdin=subprocess.PIPE) 
while True: 
    process.stdin.write("m2000\n") 
    print "bytes written" 

Sectio основной петли gpiopwm.c:

printf("1\n"); 
while (1) { 
    fgets(input,7,stdin); // Takes input from python script 
    printf("2\n"); 

    numbers = input+1;  // stores all but first char of input 
    char first = input[0]; // stores first char of input 

    if (first=='m') { 
     printf("3\n"); 
     printf("%s\n",numbers); 
    } 
} 

Однако выход из этого состоит в следующем:

1 
bytes written 
Traceback (most recent call last): 
    File "serial-receive-to-pwm.py", line 20, in <module> 
    process.stdin.write("m2000\n") 
IOError: [Errno 32] Broken pipe 

Программа C, очевидно, разрывается на линии fgets, так как 2 никогда не печатается. Что я сделал не так? Как я могу избежать этого?

EDIT: Я обновил строку fgets, чтобы он не включал аргумент разыменования, но я все еще получаю сообщение об ошибке разбитого трубопровода.

EDIT: input инициализируется как char *input="m2000";

+1

Просьба показать полное объявление (и возможную инициализацию) 'input'. –

ответ

2

Если попробовать запустить C программу из консоли, вы увидите, что он выходит из строя. И если вы бежите в отладчике, вы увидите, что он находится на этой линии:

fgets(*input,7,stdin); 

Похоже input является массив символов, и когда вы разыменования его с *input вы передаете не указатель, но один char стоимость. Это приводит к неопределенному поведению и краху.

Эта строка должна была дать вам, если не ошибку, а затем очень большое предупреждение от компилятора. Не игнорируйте предупреждающие сообщения, они часто являются показателем того, что вы делаете что-то неправильно и, возможно, опасно.


Общий совет: При разработке программы, которая должна быть вызвана из другой программы, как вы делаете здесь, теста программы сначала, чтобы убедиться, что она работает. Если он не работает, тогда исправьте его первым.

Последний совет: Помните, что fgetsсодержит новую строку в строке назначения. Вы можете проверить его и удалить, если он есть.


С последнего редактирования, показывая декларацию input мы знаем проблему реального: Вы пытаетесь изменить постоянные данные и также вы хотите написать за пределы данных, а также.

Когда вы делаете input, указывайте на литеральную строку, вы должны помнить, что все литеральные строки: только, вы не можете изменить литеральную строку. Попытка сделать это - неопределенное поведение. Чтобы усугубить ситуацию, ваша строка длиной всего шесть символов, но вы пытаетесь записать на нее семь символов.

Первая замена декларация и инициализация input:

char input[16] = "m2000\n"; 

Это будет объявить его как массив, расположенный в стеке, и которые могут быть изменены. Затем сделайте

while (fgets(input, sizeof(input), stdin) != NULL) { ... } 

Это выполняет две вещи: во-первых, используя sizeof(input) как размер, вы можете быть уверены, что fgets никогда не выписывают границ. Во-вторых, используя вызов fgets в условии цикла, цикл завершится, когда скрипт Python будет прерван, и вы не будете навсегда зацикливаться на чтении и затем работать с данными, которые вы никогда не читали.

+1

Было бы неплохо () ** также ** прямо сказать OP ** как ** исправить эту проблему? ;-) – alk

+0

Я уже говорил, что ошибка была в строке fgets. Компилятор работал отлично, иначе он не был бы скомпилирован. – theoB610

+0

@ theoB610: Предположим, что 'char input [по крайней мере 7];' Между тем попробуйте это: 'fgets (input, 7, stdin);' – alk

 Смежные вопросы

  • Нет связанных вопросов^_^