read(2) blocking behaviour changes when pts is closed resulting in read() returning error: -1 (EIO)

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
0
down vote

favorite












I'm trying to figure out how I can reliably loop a read on a pt master I have.
I open the ptmx, grant and unlock it as per usual:



* ptmx stuff */
/* get the master (ptmx) */
int32_t masterfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
if(masterfd < 0)
perror("open");
exit(EXIT_FAILURE);
;

/* grant access to the slave */
if(grantpt(masterfd) < 0)
perror("grantpt");
exit(EXIT_FAILURE);
;

/* unlock the slave */
if(unlockpt(masterfd) < 0)
perror("unlockpt");
exit(EXIT_FAILURE);
;

comms_in->ptmx = masterfd;


Next I save the slave's name (yes I know sizeof(char) is always 1)



/* get the path to the slave */
char * slavepathPtr;
char * slavePath;
size_t slavepathLen;
if((slavepathPtr = ptsname(masterfd)) == NULL)
perror("ptsname");
exit(EXIT_FAILURE);
else
slavepathLen = strlen(slavepathPtr);
slavePath = (char *) malloc(sizeof(char) * (slavepathLen + 1));
strcpy(slavePath, slavepathPtr);
;


I then create a predictably named symlink to the slave (/dev/pts/number) in /dev/custom/predictable (which was provided as an argument to this program using getopts) and verify that its permissions are safe using calls to access, lstat, readlink, symlink and confirm that the program can continue execution, otherwise it calls unlink on the symlink and terminates the thread.



Finally the program ends up in this loop



ssize_t read_result;
ssize_t write_result;
while(1)
if((read_result = read(comms_in->ptmx, ptmxio_read_buffer, sizeof ptmxio_read_buffer)) <= 0)
/** calls thread ender routine */
pthread_mutex_lock(&COMMS_MUTEX);
comms_in->thread_statuses[PTMXIO_THREAD] = THREAD_FAILED;
pthread_mutex_unlock(&COMMS_MUTEX);
pthread_cond_signal(&SIG_PROGRAM_FINISHED);
pthread_exit((void *) comms_in);

else if((write_result = write(STDOUT_FILENO, ptmxio_read_buffer, read_result)) != read_result)

/** same as above */

;
;


On the system, I can run this program and all is swell.
The read blocks.
When the pts symlink is opened with cu or picocom then bytes are successfully read up to the buffer limits either on my end or the kernel's end, depending on who's lower.
The problem comes when the slave is closed.
At this point, the read returns -1 -> EIO with error text: Input/output error and will continue to do so, consuming a lot of cpu time if I choose to not terminate the thread and loop.
When cu or picocom or even just an echo -en "some text" > /dev/pts/number, the read blocks again, until bytes are available. In the case of the redirection into the symlink, obviously if it fills less than a buffer, read just gets that one buffer and continues to return -1 -> EIO again.



What's going on? I need a method that doesn't consume a lot of CPU as this runs on a slow embedded application processor and allows me to re-establish reads without losing bytes.



I noticed a thread making a call to this:
ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, B38400 opost isig icanon echo ...) and can't make much sense of what the 3 options are as they're not in my Linux headers anywhere.. Note that 3 is comms_in->ptmx / masterfd.










share|improve this question

























    up vote
    0
    down vote

    favorite












    I'm trying to figure out how I can reliably loop a read on a pt master I have.
    I open the ptmx, grant and unlock it as per usual:



    * ptmx stuff */
    /* get the master (ptmx) */
    int32_t masterfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
    if(masterfd < 0)
    perror("open");
    exit(EXIT_FAILURE);
    ;

    /* grant access to the slave */
    if(grantpt(masterfd) < 0)
    perror("grantpt");
    exit(EXIT_FAILURE);
    ;

    /* unlock the slave */
    if(unlockpt(masterfd) < 0)
    perror("unlockpt");
    exit(EXIT_FAILURE);
    ;

    comms_in->ptmx = masterfd;


    Next I save the slave's name (yes I know sizeof(char) is always 1)



    /* get the path to the slave */
    char * slavepathPtr;
    char * slavePath;
    size_t slavepathLen;
    if((slavepathPtr = ptsname(masterfd)) == NULL)
    perror("ptsname");
    exit(EXIT_FAILURE);
    else
    slavepathLen = strlen(slavepathPtr);
    slavePath = (char *) malloc(sizeof(char) * (slavepathLen + 1));
    strcpy(slavePath, slavepathPtr);
    ;


    I then create a predictably named symlink to the slave (/dev/pts/number) in /dev/custom/predictable (which was provided as an argument to this program using getopts) and verify that its permissions are safe using calls to access, lstat, readlink, symlink and confirm that the program can continue execution, otherwise it calls unlink on the symlink and terminates the thread.



    Finally the program ends up in this loop



    ssize_t read_result;
    ssize_t write_result;
    while(1)
    if((read_result = read(comms_in->ptmx, ptmxio_read_buffer, sizeof ptmxio_read_buffer)) <= 0)
    /** calls thread ender routine */
    pthread_mutex_lock(&COMMS_MUTEX);
    comms_in->thread_statuses[PTMXIO_THREAD] = THREAD_FAILED;
    pthread_mutex_unlock(&COMMS_MUTEX);
    pthread_cond_signal(&SIG_PROGRAM_FINISHED);
    pthread_exit((void *) comms_in);

    else if((write_result = write(STDOUT_FILENO, ptmxio_read_buffer, read_result)) != read_result)

    /** same as above */

    ;
    ;


    On the system, I can run this program and all is swell.
    The read blocks.
    When the pts symlink is opened with cu or picocom then bytes are successfully read up to the buffer limits either on my end or the kernel's end, depending on who's lower.
    The problem comes when the slave is closed.
    At this point, the read returns -1 -> EIO with error text: Input/output error and will continue to do so, consuming a lot of cpu time if I choose to not terminate the thread and loop.
    When cu or picocom or even just an echo -en "some text" > /dev/pts/number, the read blocks again, until bytes are available. In the case of the redirection into the symlink, obviously if it fills less than a buffer, read just gets that one buffer and continues to return -1 -> EIO again.



    What's going on? I need a method that doesn't consume a lot of CPU as this runs on a slow embedded application processor and allows me to re-establish reads without losing bytes.



    I noticed a thread making a call to this:
    ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, B38400 opost isig icanon echo ...) and can't make much sense of what the 3 options are as they're not in my Linux headers anywhere.. Note that 3 is comms_in->ptmx / masterfd.










    share|improve this question























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I'm trying to figure out how I can reliably loop a read on a pt master I have.
      I open the ptmx, grant and unlock it as per usual:



      * ptmx stuff */
      /* get the master (ptmx) */
      int32_t masterfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
      if(masterfd < 0)
      perror("open");
      exit(EXIT_FAILURE);
      ;

      /* grant access to the slave */
      if(grantpt(masterfd) < 0)
      perror("grantpt");
      exit(EXIT_FAILURE);
      ;

      /* unlock the slave */
      if(unlockpt(masterfd) < 0)
      perror("unlockpt");
      exit(EXIT_FAILURE);
      ;

      comms_in->ptmx = masterfd;


      Next I save the slave's name (yes I know sizeof(char) is always 1)



      /* get the path to the slave */
      char * slavepathPtr;
      char * slavePath;
      size_t slavepathLen;
      if((slavepathPtr = ptsname(masterfd)) == NULL)
      perror("ptsname");
      exit(EXIT_FAILURE);
      else
      slavepathLen = strlen(slavepathPtr);
      slavePath = (char *) malloc(sizeof(char) * (slavepathLen + 1));
      strcpy(slavePath, slavepathPtr);
      ;


      I then create a predictably named symlink to the slave (/dev/pts/number) in /dev/custom/predictable (which was provided as an argument to this program using getopts) and verify that its permissions are safe using calls to access, lstat, readlink, symlink and confirm that the program can continue execution, otherwise it calls unlink on the symlink and terminates the thread.



      Finally the program ends up in this loop



      ssize_t read_result;
      ssize_t write_result;
      while(1)
      if((read_result = read(comms_in->ptmx, ptmxio_read_buffer, sizeof ptmxio_read_buffer)) <= 0)
      /** calls thread ender routine */
      pthread_mutex_lock(&COMMS_MUTEX);
      comms_in->thread_statuses[PTMXIO_THREAD] = THREAD_FAILED;
      pthread_mutex_unlock(&COMMS_MUTEX);
      pthread_cond_signal(&SIG_PROGRAM_FINISHED);
      pthread_exit((void *) comms_in);

      else if((write_result = write(STDOUT_FILENO, ptmxio_read_buffer, read_result)) != read_result)

      /** same as above */

      ;
      ;


      On the system, I can run this program and all is swell.
      The read blocks.
      When the pts symlink is opened with cu or picocom then bytes are successfully read up to the buffer limits either on my end or the kernel's end, depending on who's lower.
      The problem comes when the slave is closed.
      At this point, the read returns -1 -> EIO with error text: Input/output error and will continue to do so, consuming a lot of cpu time if I choose to not terminate the thread and loop.
      When cu or picocom or even just an echo -en "some text" > /dev/pts/number, the read blocks again, until bytes are available. In the case of the redirection into the symlink, obviously if it fills less than a buffer, read just gets that one buffer and continues to return -1 -> EIO again.



      What's going on? I need a method that doesn't consume a lot of CPU as this runs on a slow embedded application processor and allows me to re-establish reads without losing bytes.



      I noticed a thread making a call to this:
      ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, B38400 opost isig icanon echo ...) and can't make much sense of what the 3 options are as they're not in my Linux headers anywhere.. Note that 3 is comms_in->ptmx / masterfd.










      share|improve this question













      I'm trying to figure out how I can reliably loop a read on a pt master I have.
      I open the ptmx, grant and unlock it as per usual:



      * ptmx stuff */
      /* get the master (ptmx) */
      int32_t masterfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
      if(masterfd < 0)
      perror("open");
      exit(EXIT_FAILURE);
      ;

      /* grant access to the slave */
      if(grantpt(masterfd) < 0)
      perror("grantpt");
      exit(EXIT_FAILURE);
      ;

      /* unlock the slave */
      if(unlockpt(masterfd) < 0)
      perror("unlockpt");
      exit(EXIT_FAILURE);
      ;

      comms_in->ptmx = masterfd;


      Next I save the slave's name (yes I know sizeof(char) is always 1)



      /* get the path to the slave */
      char * slavepathPtr;
      char * slavePath;
      size_t slavepathLen;
      if((slavepathPtr = ptsname(masterfd)) == NULL)
      perror("ptsname");
      exit(EXIT_FAILURE);
      else
      slavepathLen = strlen(slavepathPtr);
      slavePath = (char *) malloc(sizeof(char) * (slavepathLen + 1));
      strcpy(slavePath, slavepathPtr);
      ;


      I then create a predictably named symlink to the slave (/dev/pts/number) in /dev/custom/predictable (which was provided as an argument to this program using getopts) and verify that its permissions are safe using calls to access, lstat, readlink, symlink and confirm that the program can continue execution, otherwise it calls unlink on the symlink and terminates the thread.



      Finally the program ends up in this loop



      ssize_t read_result;
      ssize_t write_result;
      while(1)
      if((read_result = read(comms_in->ptmx, ptmxio_read_buffer, sizeof ptmxio_read_buffer)) <= 0)
      /** calls thread ender routine */
      pthread_mutex_lock(&COMMS_MUTEX);
      comms_in->thread_statuses[PTMXIO_THREAD] = THREAD_FAILED;
      pthread_mutex_unlock(&COMMS_MUTEX);
      pthread_cond_signal(&SIG_PROGRAM_FINISHED);
      pthread_exit((void *) comms_in);

      else if((write_result = write(STDOUT_FILENO, ptmxio_read_buffer, read_result)) != read_result)

      /** same as above */

      ;
      ;


      On the system, I can run this program and all is swell.
      The read blocks.
      When the pts symlink is opened with cu or picocom then bytes are successfully read up to the buffer limits either on my end or the kernel's end, depending on who's lower.
      The problem comes when the slave is closed.
      At this point, the read returns -1 -> EIO with error text: Input/output error and will continue to do so, consuming a lot of cpu time if I choose to not terminate the thread and loop.
      When cu or picocom or even just an echo -en "some text" > /dev/pts/number, the read blocks again, until bytes are available. In the case of the redirection into the symlink, obviously if it fills less than a buffer, read just gets that one buffer and continues to return -1 -> EIO again.



      What's going on? I need a method that doesn't consume a lot of CPU as this runs on a slow embedded application processor and allows me to re-establish reads without losing bytes.



      I noticed a thread making a call to this:
      ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, B38400 opost isig icanon echo ...) and can't make much sense of what the 3 options are as they're not in my Linux headers anywhere.. Note that 3 is comms_in->ptmx / masterfd.







      read pts






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 11 mins ago









      Supernovah

      1063




      1063

























          active

          oldest

          votes











          Your Answer








          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "106"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "",
          contentPolicyHtml: "",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f478815%2fread2-blocking-behaviour-changes-when-pts-is-closed-resulting-in-read-return%23new-answer', 'question_page');

          );

          Post as a guest



































          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes















           

          draft saved


          draft discarded















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f478815%2fread2-blocking-behaviour-changes-when-pts-is-closed-resulting-in-read-return%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          How to check contact read email or not when send email to Individual?

          Displaying single band from multi-band raster using QGIS

          How many registers does an x86_64 CPU actually have?