Beispiel #1
0
int main(int argc, const char *argv[])
{
  /*
   * a subprocess will initially inherit the process group of its parent. the
   * process group may have a control terminal associated with it, which would
   * be the first tty device opened by the group leader. typically the group
   * leader is your shell and the control terminal is your login device. a
   * subset of signals triggered on the control terminal are sent to all members
   * of the process group, in large part to facilitate sane and consistent
   * cleanup (ex: control terminal was closed).
   *
   * so why the overly descriptive lecture style comment?
   *   1. SIGINT and SIGQUIT are among the signals with this behavior
   *   2. a number of applications gank the above for their own use
   *   3. ruby's insanely useful "guard" is one of these applications
   *   4. despite having some level of understanding of POSIX signals and a few
   *      of the scenarios that might cause problems, i learned this one only
   *      after reading ruby 1.9's process.c
   *   5. if left completely undocumented, even slightly obscure bugfixes
   *      may be removed as cruft by a future maintainer
   *
   * hindsight is 20/20 addition: if you're single-threaded and blocking on IO
   * with a subprocess, then handlers for deferrable signals might not get run
   * when you expect them to. In the case of Ruby 1.8, that means making use of
   * IO::select, which will preserve correct signal handling behavior.
   */
  if (setpgid(0,0) < 0) {
    fprintf(stderr, "Unable to set new process group.\n");
    return 1;
  }

  parse_cli_settings(argc, argv);

  FSEventStreamContext context = {0, NULL, NULL, NULL, NULL};
  FSEventStreamRef stream;
  stream = FSEventStreamCreate(kCFAllocatorDefault,
                               (FSEventStreamCallback)&callback,
                               &context,
                               config.paths,
                               config.sinceWhen,
                               config.latency,
                               config.flags);

#ifdef DEBUG
  FSEventStreamShow(stream);
  fprintf(stderr, "\n");
  fflush(stderr);
#endif

  FSEventStreamScheduleWithRunLoop(stream,
                                   CFRunLoopGetCurrent(),
                                   kCFRunLoopDefaultMode);
  FSEventStreamStart(stream);
  CFRunLoopRun();
  FSEventStreamFlushSync(stream);
  FSEventStreamStop(stream);

  return 0;
}
Beispiel #2
0
Datei: eyed.c Projekt: rsms/eye
static FSEventStreamRef my_FSEventStreamCreate(const char **paths, size_t num_paths)
{
  void         *user_data = (void *)(num_paths ? paths[0] : "?");
  FSEventStreamContext  context = {0, user_data, NULL, NULL, NULL};
  FSEventStreamRef    streamRef = NULL;
  CFMutableArrayRef   cfArray;
  
  // Settings
  FSEventStreamEventId sinceWhen = kFSEventStreamEventIdSinceNow;
  int                  flags = 0;
  CFAbsoluteTime       latency = 5.0; // How long it takes from that something 
                                      // happened to an event is dispatched.
  
  // Used as buffer for absolutize_path
  char abspath[PATH_MAX];
  
  // Create paths array
  cfArray = CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
  if (NULL == cfArray) {
    log_error("CFArrayCreateMutable() => NULL");
    goto Return;
  }
  
  // Add paths to array
  for(int i=0; i<num_paths; i++) {
    absolutize_path(paths[i], abspath);
    CFStringRef cfStr = CFStringCreateWithCString(kCFAllocatorDefault, abspath, kCFStringEncodingUTF8);
    if (NULL == cfStr) {
      CFRelease(cfArray);
      goto Return;
    }
    CFArraySetValueAtIndex(cfArray, i, cfStr);
    CFRelease(cfStr);
  }
  
  // Create the stream
  streamRef = FSEventStreamCreate(kCFAllocatorDefault,
                  (FSEventStreamCallback)&fsevents_callback,
                  &context,
                  cfArray,
                  /*settings->*/sinceWhen,
                  /*settings->*/latency,
                  /*settings->*/flags);
  
  // Check if FSEventStreamCreate failed
  if (NULL == streamRef) {
    log_error("FSEventStreamCreate() failed");
    goto Return;
  }
  
  // Print the setup
  IFDEBUG(
    FSEventStreamShow(streamRef);
  )
static FSEventStreamRef
add_watch (SeafWTMonitor *monitor, const char* repo_id, const char* worktree)
{
    SeafWTMonitorPriv *priv = monitor->priv;
    const char *path = worktree;
    RepoWatchInfo *info;
    double latency = 0.25; /* unit: second */

    CFStringRef mypath = CFStringCreateWithCString (kCFAllocatorDefault,
                                                    path, kCFStringEncodingUTF8);
    CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&mypath, 1, NULL);
    FSEventStreamRef stream;

    /* Create the stream, passing in a callback */
    struct FSEventStreamContext ctx = {0, monitor, NULL, NULL, NULL};
    stream = FSEventStreamCreate(kCFAllocatorDefault,
                                 stream_callback,
                                 &ctx,
                                 pathsToWatch,
                                 kFSEventStreamEventIdSinceNow,
                                 latency,
                                 kFSEventStreamCreateFlagFileEvents /* deprecated OSX 10.6 support*/
        );

    CFRelease (mypath);
    CFRelease (pathsToWatch);

    if (!stream) {
        seaf_warning ("[wt] Failed to create event stream \n");
        return stream;
    }

    FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    FSEventStreamStart (stream);
#ifdef FSEVENT_DEBUG
    FSEventStreamShow (stream);
    seaf_debug ("[wt mon] Add repo %s watch success :%s.\n", repo_id, repo->worktree);
#endif

    pthread_mutex_lock (&priv->hash_lock);
    g_hash_table_insert (priv->handle_hash,
                         g_strdup(repo_id), (gpointer)(long)stream);

    info = create_repo_watch_info (repo_id, worktree);
    g_hash_table_insert (priv->info_hash, (gpointer)(long)stream, info);
    pthread_mutex_unlock (&priv->hash_lock);

    /* An empty path indicates repo-mgr to scan the whole worktree. */
    add_event_to_queue (info->status, WT_EVENT_CREATE_OR_UPDATE, "", NULL);
    return stream;
}
Beispiel #4
0
static FSEventStreamRef add_watch (SeafWTMonitorPriv *priv, const char* repo_id)
{
    SeafRepo *repo = NULL;
    const char *path = NULL;

    repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
    if (!repo) {
        seaf_warning ("[wt mon] cannot find repo %s.\n", repo_id);
        return 0;
    }

    path = repo->worktree;
    CFStringRef mypath = CFStringCreateWithCString (kCFAllocatorDefault,
                                                    path, kCFStringEncodingUTF8);
    CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&mypath, 1, NULL);
    FSEventStreamRef stream;

    /* Create the stream, passing in a callback */
    struct FSEventStreamContext ctx = {0, priv, NULL, NULL, NULL};
    stream = FSEventStreamCreate(kCFAllocatorDefault,
                                 stream_callback,
                                 &ctx,
                                 pathsToWatch,
                                 kFSEventStreamEventIdSinceNow,
                                 1.0,
                                 kFSEventStreamCreateFlagWatchRoot
        );

    CFRelease (mypath);
    CFRelease (pathsToWatch);

    if (!stream) {
        seaf_warning ("[wt] Failed to create event stream \n");
        return stream;
    }

    FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    FSEventStreamStart (stream);
#ifdef FSEVENT_DEBUG
    FSEventStreamShow (stream);
    seaf_debug ("[wt mon] Add repo %s watch success :%s.\n", repo_id, repo->worktree);
#endif
    return stream;
}