From 8dbec761cf858ea65900c8a094599857208d8c3a Mon Sep 17 00:00:00 2001 From: "N.N." Date: Tue, 5 Jan 2010 22:49:36 +0000 Subject: svn path=/trunk/; revision=12907 --- desiredata/src/s_inter.c | 736 ----------------------------------------------- 1 file changed, 736 deletions(-) delete mode 100644 desiredata/src/s_inter.c (limited to 'desiredata/src/s_inter.c') diff --git a/desiredata/src/s_inter.c b/desiredata/src/s_inter.c deleted file mode 100644 index 7c9919ef..00000000 --- a/desiredata/src/s_inter.c +++ /dev/null @@ -1,736 +0,0 @@ -/* Copyright (c) 1997-1999 Miller Puckette. -* For information on usage and redistribution, and for a DISCLAIMER OF ALL -* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ - -/* Pd side of the Pd/Pd-gui interface. Also, some system interface routines -that didn't really belong anywhere. */ - -#define WATCHDOGTHREAD - -#define PD_PLUSPLUS_FACE -#include "desire.h" -using namespace desire; -#include "pthread.h" -#include -#ifdef UNISTD -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif -#ifdef HAVE_BSTRING_H -#include -#endif -#if defined(_WIN32) && !defined(__CYGWIN__) -#include -#include -#include -#include -#include -#ifdef _MSC_VER -typedef int pid_t; -#endif -typedef int socklen_t; -#define EADDRINUSE WSAEADDRINUSE -#endif - -#include -#include -#include -#include -#include -#include - -#ifndef SIGIOT -#define SIGIOT SIGABRT -#endif - -#ifdef __APPLE__ -#include -#include -#include -#else -#include -#endif - -#define DEBUG_MESSUP 1 /* messages up from pd to pd-gui */ -#define DEBUG_MESSDOWN 2 /* messages down from pd-gui to pd */ - -/* T.Grill - make it a _little_ more adaptable... */ -#ifndef PDBINDIR -#define PDBINDIR "bin/" -#endif - -#ifndef WISHAPP -#define WISHAPP "wish84.exe" -#endif - -#ifdef __linux__ -#define LOCALHOST "127.0.0.1" -#else -#define LOCALHOST "localhost" -#endif - -struct t_fdpoll { - int fdp_fd; - t_fdpollfn fdp_fn; - void *fdp_ptr; -}; - -#define INBUFSIZE 16384 - -extern int sys_guisetportnumber; -static int sys_nfdpoll; -static t_fdpoll *sys_fdpoll; -static int sys_maxfd; -t_text *sys_netreceive; -static t_binbuf *inbinbuf; -t_socketreceiver *sys_socketreceiver; -extern int sys_addhist(int phase); - -/* ----------- functions for timing, signals, priorities, etc --------- */ - -#ifdef _WIN32 -static LARGE_INTEGER nt_inittime; -static double nt_freq = 0; - -static void sys_initntclock() { - LARGE_INTEGER f1; - LARGE_INTEGER now; - QueryPerformanceCounter(&now); - if (!QueryPerformanceFrequency(&f1)) { - fprintf(stderr, "pd: QueryPerformanceFrequency failed\n"); - f1.QuadPart = 1; - } - nt_freq = f1.QuadPart; - nt_inittime = now; -} - -#if 0 -/* this is a version you can call if you did the QueryPerformanceCounter - call yourself. Necessary for time tagging incoming MIDI at interrupt - level, for instance; but we're not doing that just now. */ - -double nt_tixtotime(LARGE_INTEGER *dumbass) { - if (nt_freq == 0) sys_initntclock(); - return (((double)(dumbass->QuadPart - nt_inittime.QuadPart)) / nt_freq); -} -#endif -#endif /* _WIN32 */ - - /* get "real time" in seconds; take the - first time we get called as a reference time of zero. */ -double sys_getrealtime() { -#ifndef _WIN32 - static struct timeval then; - struct timeval now; - gettimeofday(&now, 0); - if (then.tv_sec == 0 && then.tv_usec == 0) then = now; - return (now.tv_sec - then.tv_sec) + (1./1000000.) * (now.tv_usec - then.tv_usec); -#else - LARGE_INTEGER now; - QueryPerformanceCounter(&now); - if (nt_freq == 0) sys_initntclock(); - return double(now.QuadPart - nt_inittime.QuadPart) / nt_freq; -#endif -} - -int sys_pollsockets () { - struct timeval timout; - int didsomething = 0; - fd_set readset, writeset, exceptset; - timout.tv_sec = 0; - timout.tv_usec = 0; - FD_ZERO(&writeset); - FD_ZERO(&readset); - FD_ZERO(&exceptset); - t_fdpoll *fp = sys_fdpoll; - for (int i=sys_nfdpoll; i--; fp++) FD_SET(fp->fdp_fd, &readset); - select(sys_maxfd+1, &readset, &writeset, &exceptset, &timout); - for (int i=0; i= 200112L || (_POSIX_MEMLOCK - 0) >= 200112L -#include -#endif -#if (_POSIX_MEMLOCK - 0) >= 200112L -#include -#endif -void sys_set_priority(int higher) { -#if (_POSIX_PRIORITY_SCHEDULING - 0) >= 200112L - struct sched_param par; -#ifdef USEAPI_JACK - int p1 = sched_get_priority_min(SCHED_FIFO); - int p3 = (higher ? p1 + 7 : p1 + 5); -#else - int p2 = sched_get_priority_max(SCHED_FIFO); - int p3 = (higher ? p2 - 1 : p2 - 3); -#endif - par.sched_priority = p3; - if (sched_setscheduler(0,SCHED_FIFO,&par) != -1) - fprintf(stderr, "priority %d scheduling enabled.\n", p3); -#endif -#if (_POSIX_MEMLOCK - 0) >= 200112L - /* tb: force memlock to physical memory { */ - struct rlimit mlock_limit; - mlock_limit.rlim_cur=0; - /* tb: only if we are really root we can set the hard limit */ - mlock_limit.rlim_max = getuid() ? 100 : 0; - setrlimit(RLIMIT_MEMLOCK,&mlock_limit); - /* } tb */ - if (mlockall(MCL_FUTURE) != -1) fprintf(stderr, "memory locking enabled.\n"); -#endif -} -#endif /* __linux__ */ - -#ifdef IRIX /* hack by at 2003/09/21 */ - -#if (_POSIX_PRIORITY_SCHEDULING - 0) >= 200112L || (_POSIX_MEMLOCK - 0) >= 200112L -#include -#endif - -void sys_set_priority(int higher) { -#if (_POSIX_PRIORITY_SCHEDULING - 0) >= 200112L - struct sched_param par; - /* Bearing the table found in 'man realtime' in mind, I found it a */ - /* good idea to use 192 as the priority setting for Pd. Any thoughts? */ - if (higher) par.sched_priority = 250; /* priority for watchdog */ - else par.sched_priority = 192; /* priority for pd (DSP) */ - if (sched_setscheduler(0, SCHED_FIFO, &par) != -1) - fprintf(stderr, "priority %d scheduling enabled.\n", par.sched_priority); -#endif - -#if (_POSIX_MEMLOCK - 0) >= 200112L - if (mlockall(MCL_FUTURE) != -1) fprintf(stderr, "memory locking enabled.\n"); -#endif -} -/* end of hack */ -#endif /* IRIX */ - -/* ------------------ receiving incoming messages over sockets ------------- */ - -void sys_sockerror(const char *s) { -#ifdef _WIN32 - int err = WSAGetLastError(); - if (err == 10054) return; - else if (err == 10044) { - fprintf(stderr, "Warning: you might not have TCP/IP \"networking\" turned on\n"); - fprintf(stderr, "which is needed for Pd to talk to its GUI layer.\n"); - } -#else - int err = errno; -#endif /* _WIN32 */ - fprintf(stderr, "%s: %s (%d)\n", s, strerror(err), err); -} - -void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr) { - int nfd = sys_nfdpoll; - int size = nfd * sizeof(t_fdpoll); - sys_fdpoll = (t_fdpoll *)t_resizebytes(sys_fdpoll, size, size + sizeof(t_fdpoll)); - t_fdpoll *fp = sys_fdpoll + nfd; - fp->fdp_fd = fd; - fp->fdp_fn = fn; - fp->fdp_ptr = ptr; - sys_nfdpoll = nfd + 1; - if (fd >= sys_maxfd) sys_maxfd = fd + 1; -} - -void sys_rmpollfn(int fd) { - int nfd = sys_nfdpoll; - int size = nfd * sizeof(t_fdpoll); - t_fdpoll *fp = sys_fdpoll; - for (int i=nfd; i--; fp++) { - if (fp->fdp_fd == fd) { - while (i--) { - fp[0] = fp[1]; - fp++; - } - sys_fdpoll = (t_fdpoll *)t_resizebytes(sys_fdpoll, size, size - sizeof(t_fdpoll)); - sys_nfdpoll = nfd - 1; - return; - } - } - post("warning: %d removed from poll list but not found", fd); -} - -t_socketreceiver *socketreceiver_new(t_pd *owner, int fd, t_socketnotifier notifier, -t_socketreceivefn socketreceivefn, int udp) { - t_socketreceiver *x = (t_socketreceiver *)getbytes(sizeof(*x)); - x->inhead = x->intail = 0; - x->owner = owner; - x->notifier = notifier; - x->socketreceivefn = socketreceivefn; - x->udp = udp; - x->fd = fd; - x->obuf = 0; - x->next = 0; - x->inbuf = (char *)malloc(INBUFSIZE); - if (!x->inbuf) bug("t_socketreceiver"); - return x; -} - -void socketreceiver_free(t_socketreceiver *x) {free(x->inbuf); free(x);} - -/* this is in a separately called subroutine so that the buffer isn't - sitting on the stack while the messages are getting passed. */ -static int socketreceiver_doread(t_socketreceiver *x) { - char messbuf[INBUFSIZE], *bp = messbuf; - int inhead = x->inhead; - int intail = x->intail; - char *inbuf = x->inbuf; - if (intail == inhead) return 0; - for (int i=intail; i!=inhead; i=(i+1)&(INBUFSIZE-1)) { - /* ";" not preceded by "\" is a message boundary in current syntax. - in future syntax it might become more complex. */ - char c = *bp++ = inbuf[i]; - if (c == ';' && (!i || inbuf[i-1] != '\\')) { - intail = (i+1)&(INBUFSIZE-1); - binbuf_text(inbinbuf, messbuf, bp - messbuf); - x->inhead = inhead; - x->intail = intail; - return 1; - } - } - return 0; -} - -static void socketreceiver_getudp(t_socketreceiver *x, int fd) { - char buf[INBUFSIZE+1]; - int ret = recv(fd, buf, INBUFSIZE, 0); - if (ret < 0) { - sys_sockerror("recv"); - sys_rmpollfn(fd); - sys_closesocket(fd); - } else if (ret > 0) { - buf[ret] = 0; - if (buf[ret-1] == '\n') { - char *semi = strchr(buf, ';'); - if (semi) *semi = 0; - binbuf_text(inbinbuf, buf, strlen(buf)); - outlet_setstacklim(); - x->socketreceivefn(x->owner, inbinbuf); - } else {/*bad buffer ignored */} - } -} - -void sys_exit(); - -void socketreceiver_read(t_socketreceiver *x, int fd) { - if (x->udp) {socketreceiver_getudp(x, fd); return;} - /* else TCP */ - int readto = x->inhead >= x->intail ? INBUFSIZE : x->intail-1; - /* the input buffer might be full. If so, drop the whole thing */ - if (readto == x->inhead) { - fprintf(stderr, "pd: dropped message from gui\n"); - x->inhead = x->intail = 0; - readto = INBUFSIZE; - } else { - int ret = recv(fd, x->inbuf+x->inhead, readto-x->inhead, 0); - if (ret<=0) { - if (ret<0) sys_sockerror("recv"); else post("EOF on socket %d", fd); - if (x->notifier) x->notifier(x->owner); - sys_rmpollfn(fd); - sys_closesocket(fd); - return; - } - x->inhead += ret; - if (x->inhead >= INBUFSIZE) x->inhead = 0; - while (socketreceiver_doread(x)) { - outlet_setstacklim(); - x->socketreceivefn(x->owner, inbinbuf); - } - } -} - -void sys_closesocket(int fd) { -#ifdef UNISTD - close(fd); -#endif -#ifdef _WIN32 - closesocket(fd); -#endif /* _WIN32 */ -} - -/* ---------------------- sending messages to the GUI ------------------ */ -#define GUI_ALLOCCHUNK 8192 -#define GUI_UPDATESLICE 512 /* how much we try to do in one idle period */ -#define GUI_BYTESPERPING 1024 /* how much we send up per ping */ - -static void sys_trytogetmoreguibuf(t_socketreceiver *self, int newsize) { - self->osize = newsize; - self->obuf = (char *)realloc(self->obuf, newsize); -} - -#undef max /* for msys compat */ -int max(int a, int b) { return ((a)>(b)?(a):(b)); } - -std::ostringstream lost_posts; - -void sys_vgui(const char *fmt, ...) { - t_socketreceiver *self = sys_socketreceiver; - va_list ap; - va_start(ap, fmt); - if (!self) {voprintf(lost_posts,fmt,ap); va_end(ap); return;} - if (!self->obuf) { - self->obuf = (char *)malloc(GUI_ALLOCCHUNK); - self->osize = GUI_ALLOCCHUNK; - self->ohead = self->otail = 0; - } - if (self->ohead > self->osize - GUI_ALLOCCHUNK/2) - sys_trytogetmoreguibuf(self,self->osize + GUI_ALLOCCHUNK); - int msglen = vsnprintf(self->obuf+self->ohead, self->osize-self->ohead, fmt, ap); - va_end(ap); - if(msglen < 0) {fprintf(stderr, "Pd: buffer space wasn't sufficient for long GUI string\n"); return;} - if (msglen >= self->osize - self->ohead) { - int msglen2, newsize = self->osize+1+max(msglen,GUI_ALLOCCHUNK); - sys_trytogetmoreguibuf(self,newsize); - va_start(ap, fmt); - msglen2 = vsnprintf(self->obuf+self->ohead, self->osize-self->ohead, fmt, ap); - va_end(ap); - if (msglen2 != msglen) bug("sys_vgui"); - if (msglen >= self->osize-self->ohead) msglen = self->osize-self->ohead; - } - self->ohead += msglen; - self->bytessincelastping += msglen; -} - -void sys_gui(const char *s) {sys_vgui("%s", s);} - -static int sys_flushtogui(t_socketreceiver *self) { - int writesize = self->ohead-self->otail; - if (!writesize) return 0; - int nwrote = send(self->fd, self->obuf+self->otail, writesize, 0); - if (nwrote < 0) { - perror("pd-to-gui socket"); - sys_bail(1); - } else if (!nwrote) { - return 0; - } else if (nwrote >= self->ohead-self->otail) { - self->ohead = self->otail = 0; - } else if (nwrote) { - self->otail += nwrote; - if (self->otail > self->osize>>2) { - memmove(self->obuf, self->obuf+self->otail, self->ohead-self->otail); - self->ohead -= self->otail; - self->otail = 0; - } - } - return 1; -} - -void glob_ping(t_pd *dummy) {t_socketreceiver *self = sys_socketreceiver; self->waitingforping = 0;} - -int sys_pollgui() { - if (sys_socketreceiver) sys_flushtogui(sys_socketreceiver); - return sys_pollsockets(); -} - -/* --------------------- starting up the GUI connection ------------- */ - -#ifdef __linux__ -void glob_watchdog(t_pd *dummy) { -#ifndef WATCHDOGTHREAD - if (write(sys_watchfd, "\n", 1) < 1) { - fprintf(stderr, "pd: watchdog process died\n"); - sys_bail(1); - } -#endif -} -#endif - -static void sys_setsignals() { -#ifdef UNISTD - signal(SIGHUP, sys_huphandler); - signal(SIGINT, sys_exithandler); - signal(SIGQUIT, sys_exithandler); - signal(SIGILL, sys_exithandler); - signal(SIGIOT, sys_exithandler); - signal(SIGFPE, SIG_IGN); -/* signal(SIGILL, sys_exithandler); - signal(SIGBUS, sys_exithandler); - signal(SIGSEGV, sys_exithandler); */ - signal(SIGPIPE, SIG_IGN); - signal(SIGALRM, SIG_IGN); -/* GG says: don't set SIGSTKFLT */ -#endif -} - -//t_pd *pd_new3(const char *s); - -extern "C" t_text *netreceive_new(t_symbol *compatflag, t_floatarg fportno, t_floatarg udpflag); -static int sys_start_watchdog_thread(); -static void sys_setpriority(); -extern t_text *manager; - -int sys_startgui() { -#ifdef _WIN32 - short version = MAKEWORD(2, 0); - WSADATA nobby; - if (WSAStartup(version, &nobby)) sys_sockerror("WSAstartup"); -#endif /* _WIN32 */ - /* create an empty FD poll list */ - sys_fdpoll = (t_fdpoll *)t_getbytes(0); - sys_nfdpoll = 0; - inbinbuf = binbuf_new(); - sys_setsignals(); - sys_netreceive = netreceive_new(&s_,sys_guisetportnumber,0); -// fprintf(stderr,"sys_netreceive=%p\n",sys_netreceive); - if (!sys_netreceive) return 0; -// obj_connect(sys_netreceive,0,(t_text *)pd_new3("print left"),0); -// obj_connect(sys_netreceive,1,(t_text *)pd_new3("print right"),0); - obj_connect(sys_netreceive,0,manager,0); -#if defined(__linux__) || defined(IRIX) -/* now that we've spun off the child process we can promote our process's - priority, if we can and want to. If not specfied (-1), we check root - status. This misses the case where we might have permission from a - "security module" (linux 2.6) -- I don't know how to test for that. - The "-rt" flag must be set in that case. */ - if (sys_hipriority == -1) sys_hipriority = !getuid() || !geteuid(); -#endif - if (sys_hipriority) sys_setpriority(); -#ifndef MSW - setuid(getuid()); -#endif /* MSW */ - return 0; -} - -/* To prevent lockup, we fork off a watchdog process with higher real-time - priority than ours. The GUI has to send a stream of ping messages to the - watchdog THROUGH the Pd process which has to pick them up from the GUI - and forward them. If any of these things aren't happening the watchdog - starts sending "stop" and "cont" signals to the Pd process to make it - timeshare with the rest of the system. (Version 0.33P2 : if there's no - GUI, the watchdog pinging is done from the scheduler idle routine in this - process instead.) */ -void sys_setpriority() { -#if defined(__linux__) || defined(IRIX) -#ifndef WATCHDOGTHREAD - int pipe9[2]; - if (pipe(pipe9) < 0) { - setuid(getuid()); - sys_sockerror("pipe"); - return 1; - } - int watchpid = fork(); - if (watchpid < 0) { - setuid(getuid()); - if (errno) perror("sys_startgui"); else fprintf(stderr, "sys_startgui failed\n"); - return 1; - } else if (!watchpid) { /* we're the child */ - sys_set_priority(1); - setuid(getuid()); - if (pipe9[1]) { - dup2(pipe9[0], 0); - close(pipe9[0]); - } - close(pipe9[1]); - sprintf(cmdbuf, "%s/pd-watchdog\n", guidir); - if (sys_verbose) fprintf(stderr, "%s", cmdbuf); - execl("/bin/sh", "sh", "-c", cmdbuf, (char*)0); - perror("pd: exec"); - _exit(1); - } else { /* we're the parent */ - sys_set_priority(0); - setuid(getuid()); - close(pipe9[0]); - sys_watchfd = pipe9[1]; - /* We also have to start the ping loop in the GUI; this is done later when the socket is open. */ - } -#else - sys_start_watchdog_thread(); - sys_set_priority(0); -#endif -#endif /* __linux__ */ -#ifdef MSW - if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) - fprintf(stderr, "pd: couldn't set high priority class\n"); -#endif -#ifdef __APPLE__ - if (sys_hipriority) { - struct sched_param param; - int policy = SCHED_RR; - param.sched_priority = 80; /* adjust 0 : 100 */ - int err = pthread_setschedparam(pthread_self(), policy, ¶m); - if (err) post("warning: high priority scheduling failed"); - } -#endif /* __APPLE__ */ - if (!sys_nogui) { - /* here is where we start the pinging. */ -#if defined(__linux__) || defined(IRIX) -#ifndef WATCHDOGTHREAD - if (sys_hipriority) sys_gui("pdtk_watchdog\n"); -#endif -#endif - } -} - -/* This is called when something bad has happened, like a segfault. -Call glob_quit() below to exit cleanly. -LATER try to save dirty documents even in the bad case. */ -void sys_bail(int n) { - static int reentered = 0; - if (reentered) _exit(1); - reentered = 1; - fprintf(stderr, "closing audio...\n"); - sys_close_audio(); - fprintf(stderr, "closing MIDI...\n"); - sys_close_midi(); - fprintf(stderr, "... done.\n"); - exit(n); -} - -extern "C" void glob_closeall(void *dummy, t_floatarg fforce); - -void glob_quit(void *dummy) { - glob_closeall(0, 1); - sys_bail(0); -} - -static pthread_t watchdog_id; -static pthread_t main_pd_thread; -static pthread_mutex_t watchdog_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t watchdog_cond = PTHREAD_COND_INITIALIZER; -static void *watchdog_thread(void *); - -/* start a high priority watchdog thread */ -#ifndef MSW -static int sys_start_watchdog_thread() { - pthread_attr_t w_attr; - main_pd_thread = pthread_self(); - pthread_attr_init(&w_attr); - pthread_attr_setschedpolicy(&w_attr, SCHED_FIFO); /* use rt scheduling */ - int status = pthread_create(&watchdog_id, &w_attr, (void*(*)(void*)) watchdog_thread, NULL); - return status; /* what is this function supposed to return anyway? it tried returning void though declared as int */ -} -#endif -#ifdef MSW -int gettimeofday (struct timeval *tv, void *tz); -#endif - -static t_int* watchdog_callback(t_int *dummy) { - /* signal the condition */ - pthread_cond_signal(&watchdog_cond); - return 0; -} - -/* this watchdog thread registers an idle callback once a minute - if the idle callback isn't excecuted within one minute, we're probably - blocking the system. - kill the whole process! -*/ - -static void *watchdog_thread(void *dummy) { - sys_set_priority(1); - post("watchdog thread started"); - sys_microsleep(60*1000*1000); /* wait 60 seconds ... hoping that everything is set up */ - post("watchdog thread active"); - while (1) { - struct timespec timeout; - struct timeval now; - int status; - gettimeofday(&now,0); - timeout.tv_sec = now.tv_sec + 15; /* timeout: 15 seconds */ - timeout.tv_nsec = now.tv_usec * 1000; - sys_callback((t_int(*)(t_int*))watchdog_callback, 0, 0); - status = pthread_cond_timedwait(&watchdog_cond, &watchdog_mutex, &timeout); - if (status) { -#if defined(__linux__) || defined(IRIX) - fprintf(stderr, "watchdog killing"); - kill(0,9); /* kill parent thread */ -#endif - } - sys_microsleep(15*1000*1000); /* and sleep for another 15 seconds */ - } - return 0; /* avoid warning */ -} -- cgit v1.2.1