sq5bpf / telive

Tetra live monitor
GNU General Public License v3.0
281 stars 103 forks source link

Segfaults on OS X after attempted tplay. #1

Open TheSkorm opened 8 years ago

TheSkorm commented 8 years ago

First off. Thanks heaps for writing this program.

I've been playing with getting this running in OS X. I'm able to start up telive (via rxx) and can see Tetra things happening but as soon as it goes to tplay it'll throw the PLAYBACK PROBLEM!! (fix tplay) file followed by a segfault ./rxx: line 70: 19020 Segmentation fault: 11 (core dumped) ./telive.

I'll post some gdb info once I get gdb running (never used it on OS X before).

I'm currently working on setting up a replacement for aplay (most likely sox play) but in the mean time I'd be ok with this just saving to file for me to play later.

I've tried replacing the tplay script with just a cat command to dump the contents to a text file however the text file never fills up with anything.

My main concern is if this is actually related to tplay at all or if this is another problem I'll have to solve

Hacks for certain files to get them to compile on OS X - somewhat unrelated to this issue

(no seriously these are pretty bad hacks - I don't intend on fixing these properly but if someone was keen to make a proper macport I think it would be an awesome idea).

install gnuradio via macports

symlink/opt/local/bin/python -> /opt/local/bin/python2.7

diff --git a/telive.c b/telive.c
index 1c432f9..ae3a279 100644
--- a/telive.c
+++ b/telive.c
@@ -21,7 +21,6 @@
  * be rewritten from scratch some day :)
  */

-
 #include <fnmatch.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
@@ -541,7 +540,7 @@ int matchssi(int ssi)
        if (!ssi) return(0);
        sprintf(ssistr,"%i",ssi);
        if (strlen(ssi_filter)==0) return(1); 
-       r=fnmatch((char *)&ssi_filter,(char *)&ssistr,FNM_EXTMATCH);
+       r=fnmatch((char *)&ssi_filter,(char *)&ssistr,0);
        return(!r);
 }

osmo-tetra-sq5bpf

 diff --git a/src/tunctl.c b/src/tunctl.c
 index c7b0c43..689bec3 100644
 --- a/src/tunctl.c
 +++ b/src/tunctl.c
 @@ -12,7 +12,7 @@
  #include <grp.h>
  #include <net/if.h>
  #include <sys/ioctl.h>
 -#include <linux/if_tun.h>
 +#include <net/if_utun.h>

  /* TUNSETGROUP appeared in 2.6.23 */
  #ifndef TUNSETGROUP
 @@ -40,7 +40,7 @@ int main(int argc, char **argv)
    gid_t group = -1;
    int tap_fd, opt, delete = 0, brief = 0;
    char *tun = "", *file = "/dev/net/tun", *name = argv[0], *end;
 -  unsigned int iff_type = IFF_TAP;
 +//  unsigned int iff_type = IFF_TAP;

    while((opt = getopt(argc, argv, "bd:f:t:u:g:U")) > 0){
      switch(opt) {
 @@ -85,7 +85,7 @@ int main(int argc, char **argv)
          tun = optarg;
          break;
        case 'U':
 -        iff_type = IFF_TUN;
 +        //iff_type = IFF_TUN;
          break;
        case 'h':
        default:
 @@ -107,18 +107,18 @@ int main(int argc, char **argv)

    memset(&ifr, 0, sizeof(ifr));

 -  ifr.ifr_flags = iff_type | IFF_NO_PI;
 +//  ifr.ifr_flags = iff_type | IFF_NO_PI;
    strncpy(ifr.ifr_name, tun, sizeof(ifr.ifr_name) - 1);
 -  if(ioctl(tap_fd, TUNSETIFF, (void *) &ifr) < 0){
 -    perror("TUNSETIFF");
 -    exit(1);
 -  }
 +//  if(ioctl(tap_fd, TUNSETIFF, (void *) &ifr) < 0){
 +//    perror("TUNSETIFF");
 +//    exit(1);
 +//  }

    if(delete){
 -    if(ioctl(tap_fd, TUNSETPERSIST, 0) < 0){
 -      perror("disabling TUNSETPERSIST");
 -      exit(1);
 -    }
 +//    if(ioctl(tap_fd, TUNSETPERSIST, 0) < 0){
 + //     perror("disabling TUNSETPERSIST");
 + //     exit(1);
 + //   }
      printf("Set '%s' nonpersistent\n", ifr.ifr_name);
    }
    else {
 @@ -128,10 +128,10 @@ int main(int argc, char **argv)
      }

      if(owner != -1) {
 -      if(ioctl(tap_fd, TUNSETOWNER, owner) < 0){
 -       perror("TUNSETOWNER");
 -       exit(1);
 -      }
 +   //   if(ioctl(tap_fd, TUNSETOWNER, owner) < 0){
 +   //          perror("TUNSETOWNER");
 +   //          exit(1);
 + //     }
      }
      if(group != -1) {
        if(ioctl(tap_fd, TUNSETGROUP, group) < 0){
 @@ -140,10 +140,10 @@ int main(int argc, char **argv)
        }
      }

 -    if(ioctl(tap_fd, TUNSETPERSIST, 1) < 0){
 -      perror("enabling TUNSETPERSIST");
 -      exit(1);
 -    }
 + //   if(ioctl(tap_fd, TUNSETPERSIST, 1) < 0){
 + //     perror("enabling TUNSETPERSIST");
 +  //    exit(1);
 + //   }

      if(brief)
        printf("%s\n", ifr.ifr_name);
 diff --git a/src/tuntap.c b/src/tuntap.c
 index 8109067..6f140ae 100644
 --- a/src/tuntap.c
 +++ b/src/tuntap.c
 @@ -7,8 +7,8 @@
  #include <sys/socket.h>
  #include <sys/ioctl.h>

 -#include <linux/if_tun.h>
 -#include <linux/if.h>
 +#include <net/if_utun.h>
 +#include <net/if.h>

  int tun_alloc(char *dev)
    {
 @@ -27,14 +27,14 @@ int tun_alloc(char *dev)
         *
         *        IFF_NO_PI - Do not provide packet information  
         */ 
 -      ifr.ifr_flags = IFF_TUN|IFF_NO_PI; 
 +//      ifr.ifr_flags = IFF_TUN|IFF_NO_PI; 
        if( *dev )
           strncpy(ifr.ifr_name, dev, IFNAMSIZ);

 -      if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
 -         close(fd);
 -         return err;
 -      }
 + //     if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
 +  //       close(fd);
 +  //       return err;
 +  //    }
  #if 0
        strcpy(dev, ifr.ifr_name);
  #endif

libosmocore-sq5bpf

diff --git a/src/utils.c b/src/utils.c
index cc33994..87f96b2 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -196,9 +196,10 @@ char *osmo_hexdump_nospc(const unsigned char *buf, int len)
 }

        /* Compat with previous typo to preserve abi */
-char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len)
+/*char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len)
        __attribute__((weak, alias("osmo_hexdump_nospc")));

+*/
 #include "../config.h"
 #ifdef HAVE_CTYPE_H
 #include <ctype.h>
sq5bpf commented 8 years ago

unfortunately i don't have access to a macos x box, so i can't fix the tplay problems (but if i do get access, i will look into it)

matgiani commented 8 years ago

Hello

I did some more digging and managed to get basic functionality (did not do very deep testing) running on OSX natively. In addition to @TheSkorm 's changes above, here is what I did.

tplay

diff --git a/bin/tplay b/bin/tplay
index 4c44c40..6261f0f 100755
--- a/bin/tplay
+++ b/bin/tplay
@@ -1,4 +1,7 @@
 #!/bin/sh
+#set prefix (originally /tetra)
+TPLAY_PREFIX=/path/to/your/tetra/directory
 #play acelp .out files
-cat $* | /tetra/bin/cdecoder /dev/stdin /dev/stdout | /tetra/bin/sdecoder /dev/stdin /dev/stdout | aplay -fS16_LE
+#cat $* | /tetra/bin/cdecoder /dev/stdin /dev/stdout | /tetra/bin/sdecoder /dev/stdin /dev/stdout | aplay -fS16_LE
+/bin/cat $* | $TPLAY_PREFIX/bin/cdecoder /dev/stdin /dev/stdout | $TPLAY_PREFIX/bin/sdecoder /dev/stdin /dev/stdout | /opt/local/bin/play -e signed-integer -b 16 -r 8000 -t raw -

For some reason (did not get to the bottom of it, just did a quick fix) the shell interpreting tplay did not honor $PATH when invoked by popen(), so I specified full path names explicitly. Also I added a $TPLAY_PREFIX variable as I wanted to be able to install the /tetra tree elsewhere than the root. Finally I used SoX from MacPorts in place of aplay.

telive.c

diff --git a/telive.c b/telive.c
index 1c432f9..ac22f1e 100644
--- a/telive.c
+++ b/telive.c
@@ -541,7 +541,7 @@ int matchssi(int ssi)
        if (!ssi) return(0);
        sprintf(ssistr,"%i",ssi);
        if (strlen(ssi_filter)==0) return(1); 
-       r=fnmatch((char *)&ssi_filter,(char *)&ssistr,FNM_EXTMATCH);
+       r=fnmatch((char *)&ssi_filter,(char *)&ssistr,0);
        return(!r);
 }

@@ -845,9 +845,14 @@ void tickf ()
        if (curplayingidx) {
                /* crude hack to hack around buffering, i know this should be done better */
                if (curplayingticks==2) {
-                       if (playingfp) fclose(playingfp);
-                       playingfp=popen("tplay >/dev/null 2>&1","w");
-
+                       if (playingfp) pclose(playingfp);
+                       if(!(playingfp=popen("tplay >/dev/null 2>&1","w")))
+                       {
+                               // MG edits
+                               printf("ERROR invoking tplay!");
+                               exit(1);
+                       }
+                       
                }
                curplayingticks++;
        }
@@ -1219,7 +1224,7 @@ int parsetraffic(unsigned char *buf)
                        }
                        ssis[usage].play=1;
                        if (!ps_mute)   {
-                               if (!ferror(playingfp)) {
+                               if (playingfp && !ferror(playingfp)) {
                                        fwrite(c,1,len,playingfp);
                                        fflush(playingfp);
                                } else {
@@ -1332,7 +1337,17 @@ int main(void)
        if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
                diep("socket");

-       playingfp=popen("tplay >/dev/null 2>&1","w");
+       if(!(playingfp=popen("tplay >/dev/null 2>&1","w")))
+       {
+               printf("ERROR invoking tplay! popen() failed.\n");
+               exit(1);
+       }
+
+       if(ferror(playingfp))
+       {
+               printf("pipe to tplay failed. :(\n");
+               exit(1);
+       }

        get_cfgenv(); 
        if (getenv("TETRA_PORT"))

A few changes I did while trying to figure out the segfault. The most relevant is using pclose() in place of fclose() for the file descriptor returned by popen(), which should be the correct way.

With your changes and these two you should be able to get tplay to work. Worked for me.

Let me know how it goes!

Matteo

sq5bpf commented 8 years ago

thanks. apparently closing a FILE* opened by popen() by fclose() works in linux (but is incorrect anyway). i've added this fix. also now i fall back to normal fnmatch behavious when FNM_EXTMATCH is it isn't defined. please check if it works for you.

btw i've not changed the libosmocore library yet , but instead of patching it maybe we should see if a new version works correctly? (and if it doesn't, maybe sending the patch to the osmocom guys would be a better idea). unfortunately i don't have access to a osx box to test.