Changeset 6c00179c26506e9c6c29dafe0367a722d38a0e23

Show
Ignore:
Timestamp:
07/11/09 18:35:56 (3 years ago)
Author:
Nedko Arnaudov <nedko@…>
Children:
7ab299672182b949469981e7707e50e77c8934c5
Parents:
d54100ef1932d5938e2a091619e07cefd04a1b04
git-committer:
Nedko Arnaudov <nedko@arnaudov.name> / 2009-07-11T18:35:56Z+0300
Message:

Detect UI launch failures and clean the mess

This often happens because of missing runtime dependencies
that python ui script needs (pygtk, pycairo, etc)

Files:
2 modified

Legend:

Unmodified
Added
Removed
  • lv2_ui.c

    r2aacbff r6c00179  
    2626#define UI_URI        "http://nedko.aranaudov.org/soft/filter/2/gui" 
    2727 
     28#define WAIT_START_TIMEOUT  3000 /* ms */ 
     29#define WAIT_ZOMBIE_TIMEOUT 3000 /* ms */ 
     30#define WAIT_STEP 100            /* ms */ 
     31 
    2832//#define FORK_TIME_MEASURE 
    2933 
     
    113117} 
    114118 
     119static 
     120bool 
     121wait_child( 
     122  pid_t pid) 
     123{ 
     124  pid_t ret; 
     125  int i; 
     126 
     127  if (pid == -1) 
     128  { 
     129    fprintf(stderr, "Can't wait for pid -1\n"); 
     130    return false; 
     131  } 
     132 
     133  for (i = 0; i < WAIT_ZOMBIE_TIMEOUT / WAIT_STEP; i++) 
     134  { 
     135    //printf("waitpid(%d): %d\n", (int)pid, i); 
     136 
     137    ret = waitpid(pid, NULL, WNOHANG); 
     138    if (ret != 0) 
     139    { 
     140      if (ret == pid) 
     141      { 
     142        //printf("child zombie with pid %d was consumed.\n", (int)pid); 
     143        return true; 
     144      } 
     145 
     146      if (ret == -1) 
     147      { 
     148        fprintf(stderr, "waitpid(%d) failed: %s\n", (int)pid, strerror(errno)); 
     149        return false; 
     150      } 
     151 
     152      fprintf(stderr, "we have waited for child pid %d to exit but we got pid %d instead\n", (int)pid, (int)ret); 
     153 
     154      return false; 
     155    } 
     156 
     157    //printf("zombie wait %d ms ...\n", WAIT_STEP); 
     158    usleep(WAIT_STEP * 1000);   /* wait 100 ms */ 
     159  } 
     160 
     161  fprintf( 
     162    stderr, 
     163    "we have waited for child with pid %d to exit for %.1f seconds and we are giving up\n", 
     164    (int)pid, 
     165    (float)((float)WAIT_START_TIMEOUT / 1000)); 
     166 
     167  return false; 
     168} 
     169 
    115170#define control_ptr ((struct control *)_this_) 
    116171 
     
    159214  else if (!strcmp(msg, "exiting")) 
    160215  { 
    161     pid_t ret; 
    162     int i; 
    163  
    164216    //printf("got UI exit notification\n"); 
    165217 
    166     /* wait tree seconds for child to exit, we dont like zombie processes */ 
    167     for (i = 0; i < 30; i++) 
    168     { 
    169       //fprintf(stderr, "waitpid(%d): %d\n", (int)control_ptr->pid, i); 
    170  
    171       ret = waitpid(control_ptr->pid, NULL, WNOHANG); 
    172       if (ret != 0) 
     218    /* for a while wait child to exit, we dont like zombie processes */ 
     219    if (!wait_child(control_ptr->pid)) 
     220    { 
     221      fprintf(stderr, "force killing misbehaved child %d (exit)\n", (int)control_ptr->pid); 
     222      if (kill(control_ptr->pid, SIGKILL) == -1) 
    173223      { 
    174         if (ret == -1) 
    175         { 
    176           fprintf(stderr, "waitpid(%d) failed: %s\n", (int)control_ptr->pid, strerror(errno)); 
    177         } 
    178         else if (ret == control_ptr->pid) 
    179         { 
    180           control_ptr->pid = -1; 
    181         } 
    182         else 
    183         { 
    184           fprintf(stderr, "we have waited for child pid %d to exit but we got pid %d instead\n", (int)control_ptr->pid, (int)ret); 
    185         } 
    186  
    187         break; 
     224        fprintf(stderr, "kill() failed: %s (exit)\n", strerror(errno)); 
    188225      } 
    189  
    190       //fprintf(stderr, "wait 100 ms ...\n"); 
    191       usleep(100000);           /* wait 100 ms */ 
    192     } 
    193  
    194     if (control_ptr->pid != -1) 
    195     { 
    196       fprintf(stderr, "we have waited for child pid %d to exit for 3 seconds and we are giving up\n", (int)control_ptr->pid); 
     226      else 
     227      { 
     228        wait_child(control_ptr->pid); 
     229      } 
    197230    } 
    198231 
     
    309342  const char * argv[8]; 
    310343  int ret; 
     344  int i; 
     345  char ch; 
    311346 
    312347  //printf("instantiate('%s', '%s') called\n", plugin_uri, bundle_path); 
     
    431466  fcntl(control_ptr->recv_pipe, F_SETFL, oldflags | O_NONBLOCK); 
    432467 
    433   *widget = (LV2UI_Widget)control_ptr; 
    434  
    435   return (LV2UI_Handle)control_ptr; 
     468  /* wait a while for child process to confirm it is alive */ 
     469  //printf("waiting UI start\n"); 
     470  i = 0; 
     471loop: 
     472  ret = read(control_ptr->recv_pipe, &ch, 1); 
     473  switch (ret) 
     474  { 
     475  case -1: 
     476    if (errno == EAGAIN) 
     477    { 
     478      if (i < WAIT_START_TIMEOUT / WAIT_STEP) 
     479      { 
     480        //printf("start wait %d ms ...\n", WAIT_STEP); 
     481        usleep(WAIT_STEP * 1000); 
     482        i++; 
     483        goto loop; 
     484      } 
     485 
     486      fprintf( 
     487        stderr, 
     488        "we have waited for child with pid %d to appear for %.1f seconds and we are giving up\n", 
     489        (int)control_ptr->pid, 
     490        (float)((float)WAIT_START_TIMEOUT / 1000)); 
     491    } 
     492    else 
     493    { 
     494      fprintf(stderr, "read() failed: %s\n", strerror(errno)); 
     495    } 
     496    break; 
     497  case 1: 
     498    if (ch == '\n') 
     499    { 
     500      *widget = (LV2UI_Widget)control_ptr; 
     501      return (LV2UI_Handle)control_ptr; 
     502    } 
     503 
     504    fprintf(stderr, "read() wrong first char '%c'\n", ch); 
     505 
     506    break; 
     507  default: 
     508    fprintf(stderr, "read() returned %d\n", ret); 
     509  } 
     510 
     511  fprintf(stderr, "force killing misbehaved child %d (start)\n", (int)control_ptr->pid); 
     512 
     513  if (kill(control_ptr->pid, SIGKILL) == -1) 
     514  { 
     515      fprintf(stderr, "kill() failed: %s (start)\n", strerror(errno)); 
     516  } 
     517 
     518  /* wait a while child to exit, we dont like zombie processes */ 
     519  wait_child(control_ptr->pid); 
    436520 
    437521fail_free_control: 
     
    439523 
    440524fail: 
     525  fprintf(stderr, "lv2fil UI launch failed\n"); 
    441526  return NULL; 
    442527} 
  • ui

    rd54100e r6c00179  
    11531153        self.send(["port_value", str(port_index), "%.10f" % value]) 
    11541154 
     1155    def send_hi(self): 
     1156        self.send([""])         # send empty line (just newline char) 
     1157 
    11551158    def recv_line(self): 
    11561159        return self.recv_pipe.readline().strip() 
     
    11981201                self.on_show() 
    11991202        else: 
     1203            self.send_hi() 
    12001204            gobject.io_add_watch(self.recv_pipe_fd, gobject.IO_IN | gobject.IO_HUP, self.on_recv) 
    12011205