linux - Executing omxplayer, on a C program, via execve/l won't output video on non-X console on child process after fork() -


hy.

i'm trying execute omxplayer (http://elinux.org/omxplayer) on raspberry pi after c fork() via execve or execl functions can save pid video playing process (so system not work). if execute program on x console/terminal works if via standard terminal (without starting x) run not output video screen if execve called on child process. way, executing player via "omxplayer ..." commnad in console play video , output screen. i'm bit new kind of things situation haven't been able solve or find answer to. here has ideia on how solve or direction give me find possible solution?

note: code execve call wich know right because in x works perfectly.

the execve() call supplies new environment executed program. program able access x display, need retain environment variables -- display @ minimum. have inadvertently omitted display new environment?

for omxplayer work without x, has have access video device (/dev/video, in case; see omxplayer builds page details). it's configured members of video group allowed access it.

you can use popen("id -gn", "r") in program, run id -gn command lists current group memberships. (read list string file handle, close using pclose().) if list not contain video, problem privileges of user running original program not include access video device. fix simple: adding video groups user member of.


here example program, run.c, illustrate basic use of execvp():

#include <unistd.h>  /* example main(): */ #include <sys/types.h> #include <sys/wait.h> #include <string.h> #include <stdio.h> #include <errno.h>  /* try executing command in child process.  * returns pid of child process,  * not tell whether execution  * successful or not.  * returns (pid_t)-1 errno set if fork() fails. */ pid_t run(char *const command[]) {     pid_t   child;      child = fork();     if (child == (pid_t)-1)         return (pid_t)-1;      if (!child) {         execvp(command[0], command);         _exit(127);     }      return child; }  int main(int argc, char *argv[]) {     pid_t child, p;     int   status;      if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {         fprintf(stderr, "\n");         fprintf(stderr, "usage: %s [ -h | --help ]\n", argv[0]);         fprintf(stderr, "       %s command [ arguments .. ]\n", argv[0]);         fprintf(stderr, "\n");         return 1;     }      child = run(argv + 1);     if (child == (pid_t)-1) {         fprintf(stderr, "%s: %s.\n", argv[1], strerror(errno));         return 1;     }      fprintf(stderr, "(%s: pid %d)\n", argv[1], (int)child);     fflush(stderr);      {         p = waitpid(child, &status, 0);         if (p == (pid_t)-1 && errno == eintr)             continue;     } while (p != child && p != (pid_t)-1);     if (p == (pid_t)-1) {         fprintf(stderr, "(%s: %s.)\n", argv[1], strerror(errno));         return 1;     }      if (wifexited(status)) {         if (wexitstatus(status) == 127)             fprintf(stderr, "(%s: not execute command.)\n", argv[1]);         else         if (wexitstatus(status) == 0)             fprintf(stderr, "(%s: exited successfully.)\n", argv[1]);         else             fprintf(stderr, "(%s: exited error %d.)\n", argv[1], wexitstatus(status));     } else     if (wifsignaled(status))         fprintf(stderr, "(%s: killed %s.)\n", argv[1], strsignal(wtermsig(status)));     else         fprintf(stderr, "(%s: died unknown causes.)\n", argv[1]);      return status; } 

you can compile , test using e.g.

gcc -w -wall -o3 run.c -o run ./run date --utc 

note run() function not attempt check whether command executed or not; returns child process pid, or (pid_t)-1 if fork() fails.

many implementations, including gnu c library popen(), use 127 exit status indication execution failed. is, not returned command should have been executed, child process, because command execution failed. above run() too.


you can use close-on-exec pipe between parent , child processes in run() function, let parent process know whether child process started desired command or not, , if not, why not. parent process can reap defunct child process. leaves little effort caller in case of errors, highly recommend approach. here example implementation:

#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/wait.h> #include <fcntl.h> #include <errno.h>  /* helper function: close file descriptor, without modifying errno.  * returns 0 if successful, otherwise errno reported close(). */ static int closefd(const int fd) {     int saved_errno, result;      /* invalid descriptor? */     if (fd == -1)         return einval;      /* save errno. it's thread-local, long restore      * before returning, no-one notice change in it. */     saved_errno = errno;      /* close descriptor, , save errno (or 0) in result. */     {         result = close(fd);     } while (result == -1 && errno == eintr);     if (result == -1)         result = errno;     else         result = 0;      /* restore errno. done. */     errno = saved_errno;      return result; }  /* helper function: create close-on-exec pipe.  * return 0 if success, errno otherwise. */ int close_on_exec_pipe(int fds[2]) {     int result;      result = pipe(fds);     if (result == -1) {         fds[0] = -1;         fds[1] = -1;         return errno;     }      {          {             result = fcntl(fds[0], f_setfd, fd_cloexec);         } while (result == -1 && errno == eintr);         if (result == -1)             break;          {             result = fcntl(fds[1], f_setfd, fd_cloexec);         } while (result == -1 && errno == eintr);         if (result == -1)             break;          /* success. */         return 0;      } while (0);      /* failed. */     closefd(fds[0]);     closefd(fds[1]);     fds[0] = -1;     fds[1] = -1;      return errno; }  /* run external command in child process.  * command[0] path or name of command,  * , array must terminated null.  *  * if successful, function return pid  * of child process. otherwise, return  * (pid_t)-1, errno indicating error. */ pid_t run(char *const command[]) {     pid_t   child, p;     int     commfd[2], errcode;      /* create close-on-exec pipe between parent , child. */     if (close_on_exec_pipe(commfd))         return (pid_t)-1;      /* fork new child process. */     child = fork();     if (child == (pid_t)-1) {         closefd(commfd[0]);         closefd(commfd[1]);         return (pid_t)-1;     }      if (!child) {         /* child process: */          /* close read/parent end of pipe. */         closefd(commfd[0]);          /* in case of c library bugs, prepare errno. */         errno = einval;          /* execute desired command. */         execvp(command[0], command);          /* failed. errno describes why. */         errcode = errno;          /* send parent via pipe. */         {             const char       *p = (char *)&errcode;             const char *const q = (char *)&errcode + sizeof errcode;             ssize_t           n;              while (p < q) {                 n = write(commfd[1], p, (size_t)(q - p));                 if (n > (ssize_t)0)                     p += n;                 else                 if (n != (ssize_t)-1)                     break;                 else                 if (errno != eintr)                     break;             }         }          /* close write/child end of pipe. */         closefd(commfd[1]);          /* exit failure (127). */         _exit(127);     }      /* parent: */      /* close write/child end of pipe. */     closefd(commfd[1]);      /* try read execution error. */     {         char       *p = (char *)&errcode;         char *const q = (char *)&errcode + sizeof errcode;         ssize_t     n;          errcode = 0;          while (p < q) {             n = read(commfd[0], p, (size_t)(q - p));             if (n > (ssize_t)0)                 p += n;             else             if (n != (ssize_t)-1)                 break; /* n == 0 pipe closed */             else             if (errno != eintr)                 break;         }          /* close read/parent end of pipe. */         closefd(commfd[0]);          /* pipe closed (on exec), no data read? */         if (n == (ssize_t)0 && p == (char *)&errcode) {             /* yes, success! */             errno = 0;             return child;         }          /* execution failed.          * if didn't reason, use einval. */         if (!errcode || p != q)             errcode = einval;     }      /* reap child process. */     {         p = waitpid(child, null, 0);         if (p == (pid_t)-1) {             if (errno == eintr)                 continue;             else                 break;         }     } while (p != child);      /* return failure. */     errno = errcode;     return (pid_t)-1; } 

the downside approach, in opinion, 2 descriptors used in parent process, albeit temporarily. in cases irrelevant, if have server-type application uses lot of file descriptors, should aware of.


the phidgets library uses threads. thread executes callbacks different 1 say, waits keypress in rfid phidgets example. 1 option use posix_spawn() execute player (from non-main thread).

however, in general, better have main thread monitor both player using waitpid(child, &status, wnohang) check if player has exited, , handle new rfid events, launching player needed (killing existing instance if new rfid), , killing player if rfid moved outside reader range.

this requires simple threaded event queue:

#define  _posix_c_source 200809l #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <pthread.h> #include <stdio.h> #include <errno.h>  /* rfid tag event types: tag read, tag lost. */ typedef enum {     rfid_tag_lost = 0,     rfid_tag_read } rfid_event_type_t;  /* structure describing possible rfid tag events. */ typedef struct rfid_event_st  rfid_event_t; struct rfid_event_st {     struct rfid_event_st     *next;     rfid_event_type_t         type;     cphidgetrfidhandle        rfid;     cphidgetrfid_protocol     protocol;     void                     *userptr;     char                      tag[]; };  static pthread_mutex_t  event_lock = pthread_mutex_initializer; static pthread_cond_t   event_wait = pthread_cond_initializer; static rfid_event_t    *event_queue = null;  /* add event event queue. */ static int add_event(const cphidgetrfidhandle rfid,                      const cphidgetrfid_protocol protocol,                      const rfid_event_type_t type,                      const char *const tag,                      void *const userptr) {     const size_t  taglen = (tag) ? strlen(tag) : 0;     rfid_event_t *ev;      /* allocate memory new event. */     ev = malloc(sizeof (rfid_event_t) + taglen + 1);     if (!ev)         return errno = enomem;      /* fill in fields. */     ev->next = null;     ev->type = type;     ev->rfid = rfid;     ev->protocol = protocol;     ev->userptr = userptr;     if (taglen > 0)         memcpy(ev->tag, tag, taglen);     ev->tag[taglen] = '\0';      /* lock event queue. */     pthread_mutex_lock(&event_lock);      /* append event queue. */     if (event_queue) {         rfid_event_t *prev = event_queue;         while (prev->next)             prev = prev->next;         prev->next = ev;     } else         event_queue = ev;      /* signal , unlock. */     pthread_cond_signal(&event_wait);     pthread_mutex_unlock(&event_lock);      return 0; }  /* next event, waiting @ 'maxwait' seconds. */ static rfid_event_t *get_event(const long maxwait) {     struct timespec until;     rfid_event_t   *ev;      pthread_mutex_lock(&event_lock);      /* event in queue? */     if (event_queue) {         ev = event_queue;         event_queue = ev->next;         ev->next = null;         pthread_mutex_unlock(&event_lock);         return ev;     }      /* no waiting requested? */     if (maxwait <= 0l) {         pthread_mutex_unlock(&event_lock);         return null;     }      /* current wall clock time, */     clock_gettime(clock_realtime, &until);     /* , add maxwait seconds. */     until.tv_sec += maxwait;      /* wait signal. */     pthread_cond_timedwait(&event_wait, &event_lock, &until);      /* event arrived in queue? */     if (event_queue) {         ev = event_queue;         event_queue = ev->next;         ev->next = null;         pthread_mutex_unlock(&event_lock);         return ev;     }      /* no event; timed out. */     pthread_mutex_unlock(&event_lock);     return null; } 

as per phidgets rfid example, tag , tag lost handlers are

int cconv taghandler(cphidgetrfidhandle rfid, void *usrptr, char *tagval, cphidgetrfid_protocol proto) {     return add_event(rfid, proto, rfid_tag_read, tagval, usrptr); }  int cconv taglosthandler(cphidgetrfidhandle rfid, void *usrptr, char *tagval, cphidgetrfid_protocol proto) {     return add_event(rfid, proto, rfid_tag_lost, tagval, usrptr); } 

instead of waiting keypress after has been set up, create loop, like

    pid_t         child = (pid_t)-1; /* not running */     pid_t         p;     rfid_event_t *event;      /* infinite loop */     while (1) {          /* have player child process? */         if (child != (pid_t)-1) {              /* yes. has exited yet? */             p = waitpid(child, null, wnohang);             if (p == child) {                 /* yes. no more player. */                 child == (pid_t)-1;             }         }          /* check new event.          * if have child, wait 1 second          * event; otherwise, wait 30 secs.         */         if (child == (pid_t)-1)             event = get_event(30l);         else             event = get_event(1l);          /* if no event yet, start @ beginning of loop. */         if (!event)             continue;          /*          * todo: handle event.          *       can stop existing player via e.g.          *       if (child != (pid_t)-1)          *           kill(child, sigkill);          *       , start new one.         */          /* discard event. it's dynamically allocated. */         free(event);     } 

if start player, above loop detects not playing within second. if there no player running, it's okay loop wait rfid signal long wants -- used 30 seconds.


Comments

Popular posts from this blog

java - nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet Hibernate+SpringMVC -

sql - Postgresql tables exists, but getting "relation does not exist" when querying -

asp.net mvc - breakpoint on javascript in CSHTML? -