Giter VIP home page Giter VIP logo

bluesignals's Introduction

APIDoc Build Status - Master macOS iOS Linux Apache 2 Slack Status

Signals

Generic Cross Platform Signal Handler.

Prerequisites

Swift

  • Swift Open Source swift-5.1-RELEASE toolchain (Minimum REQUIRED for latest release)
  • Swift Open Source swift-5.4-RELEASE toolchain (Recommended)
  • Swift toolchain included in Xcode Version 11.0 or higher.

BlueSignals version 2.0 and above supports Swift 5.1+. See older versions of BlueSSLService for older versions of Swift.

macOS

  • macOS 10.14.6 (Mojave) or higher.
  • Xcode Version 11.0 or higher using one of the above toolchains.
  • Xcode Version 12.5 or higher using the included toolchain (Recommended).

iOS

  • iOS 10.0 or higher
  • Xcode Version 11.0 or higher using one of the above toolchains.
  • Xcode Version 12.5 or higher using the included toolchain (Recommended).

Linux

  • Ubuntu 16.04 (or 16.10 but only tested on 16.04) and 18.04.
  • One of the Swift Open Source toolchain listed above.

Build

To build Signals from the command line:

% cd <path-to-clone>
% swift build

Using Signals

Including in your project

Swift Package Manager

To include BlueSignals into a Swift Package Manager package, add it to the dependencies attribute defined in your Package.swift file. You can select the version using the majorVersion and minor parameters. For example:

	dependencies: [
		.Package(url: "https://github.com/Kitura/BlueSignals.git", majorVersion: <majorVersion>, minor: <minor>)
	]

Carthage

To include BlueSignals in a project using Carthage, add a line to your Cartfile with the GitHub organization and project names and version. For example:

	github "Kitura/BlueSignals" ~> <majorVersion>.<minor>

CocoaPods

To include BlueSignals in a project using CocoaPods, you just add BlueSignals to your Podfile, for example:

    platform :ios, '10.0'

    target 'MyApp' do
        use_frameworks!
        pod 'BlueSignals'
    end

Before starting

The first thing you need to do is import the Signals framework. This is done by the following:

import Signals

Provided APIs

Signals provides four (4) class level APIs. Three (3) are used for trapping and handling operating system signals. The other function allows for the raising of a signal.

Watching a signal

SignalWatch provides an interface that allows a trapped signal to notify multiple "signal watchers". In this way, signal traps can be shared across libraries in the same application. In most cases this can be used as a direct replacement for trap().

When a signal is added via SignalWatch, it will install it's own handler on that signal via trap(). As such, it is important to not use trap() directly when using SignalWatch. If all watchers of a signal are removed, SignalWatch will intelligently restore the handler that was installed before SignalWatch.

import Signals

...
let server: SomeServer = ...


SignalWatch.shared.on(signal: .int) { _ in
 		server.shutdownServer()
}

server.run()

Trapping a signal

  • trap(signal signal: Signal, action: SigActionHandler) - This basic API allows you to set and specific handler for a specific signal.

The example below shows how to add a trap handler to a server in order to perform and orderly shutdown in the event that user press ^C which sends the process a SIGINT.

import Signals

...

let server: SomeServer = ...

Signals.trap(signal: .int) { signal in

	server.shutdownServer()
}

server.run()

Additionally, convenience API's that build on the basic API specified above are provided that will allow for trapping multiple signals, each to a separate handler or to a single handler.

  • trap(signals signals: [(signal: Signal, action: SigActionHandler)]) - This lets you trap multiple signals to separate handlers in a single function call.
  • trap(signals signals: [Signal], action: SigActionHandler) - This API lets you trap multiple signals to a common handler.

Raising a signal

  • raise(signal signal: Signal) - This API is used to send an operating system signal to your application.

This example illustrates how to use Signals to raise a signal with the OS, in this case SIGABRT.

import Signals

...

Signals.raise(signal: .abrt)

Ignoring a signal

  • func ignore(signal: Signal) - This API is used to ignore an operating system signal.

This example illustrates how to use Signals to ignore a signal with the OS, in this case SIGPIPE.

import Signals

...

Signals.ignore(signal: .pipe)

Restoring a signals default handler

  • func restore(signal: Signal) - This API is used to restore an operating system signals default handler.

This example illustrates how to use Signals to restore a signals default handler, in this case SIGPIPE.

import Signals

...

Signals.restore(signal: .pipe)

Adding a USER-DEFINED signal

This example shows how to add a user defined signal, add a trap handler for it and then raise the signal.

import Signals

let mySignal = Signals.Signal.user(20)

Signals.trap(signal: mySignal) { signal in

	print("Received signal \(signal)")
}

Signals.raise(signal: mySignal)

The output of the above snippet is:

Received signal 20

Community

We love to talk server-side Swift and Kitura. Join our Slack to meet the team!

License

This library is licensed under Apache 2.0. Full license text is available in LICENSE.

bluesignals's People

Contributors

billabt avatar dannys42 avatar djones6 avatar helenmasters avatar ianpartridge avatar kweinmeister avatar kyemaloy97 avatar quanvo87 avatar smartorelli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bluesignals's Issues

Build fails with Swift 4.2 on Ubuntu 16.04

We recently added a 4.2 CI build on Kitura which failed.
It seems BlueSignals is failing to build on Swift 4.2.

This is the error message I'm seeing:

BlueSignals/Sources/Signals/Signals.swift:111:36: error: converting non-escaping value to 'T' may allow it to escape
                        sigAction.__sigaction_handler = unsafeBitCast(action, to: sigaction.__Unnamed_union___sigaction_handler.self)

Unable to capture signals in app delegate closure.

I tried to crash my iOS 11 app by accessing out of bounds elements from an Array.

In the app delegate's did finish launching with options, I declared like the below

Signals.trap(signals: [.abrt, .alrm, .hup, .int, .kill, .pipe, .quit, .term]) { (signal) in
            print("Received signal \(signal)")
}

However, I am still not able to catch swift runtime exceptions. Pls guide.

Closures not working?

I wonder about the example code which looks to me like it is using a closure which captured context. In my similar code I get the following error:

error: a C function pointer cannot be formed from a closure that captures context

This makes it pretty hard to do anything of value inside the signal handler.

I "hacked" it with a global variable for my code but I wonder if there is a better solution for this problem or if I did something totally wrong?

Problem with signals.swift for upgraded swift version 4.2

There is an error in the file BlueSignals/Sources/Signals/Signals.swift...
The Error is as follows:
111:36: error: converting non-escaping value to 'T' may allow it to escape
sigAction.__sigaction_handler = unsafeBitCast(action, to: sigaction.__Unnamed_union___sigaction_handler.self)
^
error: terminated(1)

Illegal instruction in Linux

This code works in macOS, but results in Illegal instruction in Linux (official Swift 4.2.1 Docker image):

import Foundation
import Signals

let semaphore = DispatchSemaphore(value: 0)

class Signaler {
    static func execute() {
        semaphore.signal()
    }
}

// crashes even if closure is empty
Signals.trap(signals: [.int, .term]) { s in
    print("Trapped \(s)")
    Signaler.execute()
}

print("Now we wait")
semaphore.wait()
print("Bye!")

However, classic signal works fine both in macOS and Linux:

import Foundation

let semaphore = DispatchSemaphore(value: 0)

class Signaler {
    static func execute() {
        semaphore.signal()
    }
}

let trap: @convention(c) (Int32) -> Void = { s in
    print("Received signal \(s)")
    Signaler.execute()
}

signal(SIGINT, trap)
signal(SIGTERM, trap)

print("Now we wait")
semaphore.wait()
print("Bye!")

Invalid exclude warnings in Xcode 13

Xcode 13 shows some "Invalid exclude" warnings for these files:

  • BlueSignals/Sources/Signals/Sources/Signals.h
  • BlueSignals/Sources/Signals/Sources/Info.plist
  • BlueSignals/Sources/Signals/Signal.xcodeproj
  • BlueSignals/Sources/Signals/README.md
  • BlueSignals/Sources/Signals/Tests

Compilation failure with Swift 5.1

Attempting to build BlueSignals on Linux (or a project which depends on it - such as Kitura) with the latest Swift 5.1 snapshot (swift-5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a) fails with:

Incorrect reconstructed type for $sSay7SignalsAAC6SignalO6signal_ys5Int32VXC6actiontGD
Original type:
(bound_generic_struct_type decl=Swift.(file).Array
  (tuple_type num_elements=2
    (tuple_type_elt name=signal
      (enum_type decl=Signals.(file).Signals.Signal@/home/djones6/swift501/Kitura/.build/checkouts/BlueSignals/Sources/Signals/Signals.swift:38:14
        (parent=class_type decl=Signals.(file).Signals@/home/djones6/swift501/Kitura/.build/checkouts/BlueSignals/Sources/Signals/Signals.swift:31:14)))
    (tuple_type_elt name=action
      (function_type representation=c escaping
        (input=function_params num_params=1
          (param
            (struct_type decl=Swift.(file).Int32)))
        (output=tuple_type num_elements=0)))))
Reconstructed type:
(bound_generic_struct_type decl=Swift.(file).Array
  (tuple_type num_elements=2
    (tuple_type_elt name=signal
      (enum_type decl=Signals.(file).Signals.Signal@/home/djones6/swift501/Kitura/.build/checkouts/BlueSignals/Sources/Signals/Signals.swift:38:14
        (parent=class_type decl=Signals.(file).Signals@/home/djones6/swift501/Kitura/.build/checkouts/BlueSignals/Sources/Signals/Signals.swift:31:14)))
    (tuple_type_elt name=action
      (function_type representation=c
        (input=function_params num_params=1
          (param
            (struct_type decl=Swift.(file).Int32)))
        (output=tuple_type num_elements=0)))))
Stack dump:
0.      Program arguments: /home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift -frontend -c -primary-file /home/djones6/swift501/Kitura/.build/checkouts/BlueSignals/Sources/Signals/Signals.swift -emit-module-path /home/djones6/swift501/Kitura/.build/x86_64-unknown-linux/debug/Signals.build/Signals~partial.swiftmodule -emit-module-doc-path /home/djones6/swift501/Kitura/.build/x86_64-unknown-linux/debug/Signals.build/Signals~partial.swiftdoc -emit-dependencies-path /home/djones6/swift501/Kitura/.build/x86_64-unknown-linux/debug/Signals.build/Signals.d -emit-reference-dependencies-path /home/djones6/swift501/Kitura/.build/x86_64-unknown-linux/debug/Signals.build/Signals.swiftdeps -target x86_64-unknown-linux -disable-objc-interop -sdk / -I /home/djones6/swift501/Kitura/.build/x86_64-unknown-linux/debug -enable-testing -g -module-cache-path /home/djones6/swift501/Kitura/.build/x86_64-unknown-linux/debug/ModuleCache -swift-version 5 -Onone -D SWIFT_PACKAGE -D DEBUG -color-diagnostics -enable-anonymous-context-mangled-names -parse-as-library -module-name Signals -o /home/djones6/swift501/Kitura/.build/x86_64-unknown-linux/debug/Signals.build/Signals.swift.o -index-store-path /home/djones6/swift501/Kitura/.build/x86_64-unknown-linux/debug/index/store -index-system-modules
1.      While emitting IR SIL function "@$s7SignalsAAC4trap7signalsySayAB6SignalO6signal_ys5Int32VXC6actiontG_tFZ".
 for 'trap(signals:)' (at /home/djones6/swift501/Kitura/.build/checkouts/BlueSignals/Sources/Signals/Signals.swift:123:9)
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x48cca44]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x48ca660]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x48cce68]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7fdfe639c390]
/lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7fdfe4adb428]
/lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7fdfe4add02a]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x6e6689]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x6e6e5f]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x6e6b12]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x6de076]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x6ded3f]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x6f03c3]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x61c344]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x5865f8]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x586cd7]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x508e94]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x50451f]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x49fbdd]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fdfe4ac6830]
/home/djones6/.swiftenv/versions/5.1-DEVELOPMENT-SNAPSHOT-2019-04-17-a/usr/bin/swift[0x49f759]

This seems to relate to the @escaping attribute, and the various trap() function signatures. Specifically, there is one function that takes an array of (Signal,SigActionHandler) tuples, where the SigActionHandler is not explicitly marked as @escaping, however this is then passed to another trap() function where it is escaping.

I couldn't find a syntax that allows you to mark the SigActionHandler that is embedded in the tuple type as escaping, and to be honest I'm not sure how this currently compiles - the fact that it blows up (rather than producing a proper error) on 5.1 suggests it might be a compiler issue, but I'm not really sure.

Framework does not build under linux with latest swift-4-dev snapshot.

Please ignore this issue, if you already aware of it. I know that this is something I have to expect when I use swift 4 developer snapshots.

I modified the official swift docker image (based on ubuntu:16.04) so that it downloads the latest swift-4 snapshot. When I build Signals in this container I get following error:

/.build/checkouts/BlueSignals.git--1658853586168318266/Sources/Signals.swift:113:8: error: type of expression is ambiguous without more context
                        _ = Glibc.sigaction(signal.valueOf, &sigAction, nil)
                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Thanks,

Karsten

Dockerfile
FROM ubuntu:16.04
MAINTAINER Haris Amin <[email protected]>

# Install related packages and set LLVM 3.6 as the compiler
RUN apt-get -q update && \
    apt-get -q install -y \
    make \
    libc6-dev \
    clang-3.8 \
    curl \
    libedit-dev \
    python2.7 \
    python2.7-dev \
    libicu-dev \
    libssl-dev \
    libxml2 \
    git \
    libcurl4-openssl-dev \
    pkg-config \
    && update-alternatives --quiet --install /usr/bin/clang clang /usr/bin/clang-3.8 100 \
    && update-alternatives --quiet --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.8 100 \
    && rm -r /var/lib/apt/lists/*

# Everything up to here should cache nicely between Swift versions, assuming dev dependencies change little
ARG SWIFT_PLATFORM=ubuntu16.04
ARG SWIFT_BRANCH=swift-4.0-branch
ARG SWIFT_VERSION=swift-4.0-DEVELOPMENT-SNAPSHOT-2017-06-07-a

ENV SWIFT_PLATFORM=$SWIFT_PLATFORM \
    SWIFT_BRANCH=$SWIFT_BRANCH \
    SWIFT_VERSION=$SWIFT_VERSION

# Download GPG keys, signature and Swift package, then unpack, cleanup and execute permissions for foundation libs
RUN SWIFT_URL=https://swift.org/builds/$SWIFT_BRANCH/$(echo "$SWIFT_PLATFORM" | tr -d .)/$SWIFT_VERSION/$SWIFT_VERSION-$SWIFT_PLATFORM.tar.gz \
    && curl -fSsL $SWIFT_URL -o swift.tar.gz \
    && curl -fSsL $SWIFT_URL.sig -o swift.tar.gz.sig \
    && export GNUPGHOME="$(mktemp -d)" \
    && set -e; \
        for key in \
      # pub   4096R/412B37AD 2015-11-19 [expires: 2017-11-18]
      #       Key fingerprint = 7463 A81A 4B2E EA1B 551F  FBCF D441 C977 412B 37AD
      # uid                  Swift Automatic Signing Key #1 <[email protected]>
          7463A81A4B2EEA1B551FFBCFD441C977412B37AD \
      # pub   4096R/21A56D5F 2015-11-28 [expires: 2017-11-27]
      #       Key fingerprint = 1BE1 E29A 084C B305 F397  D62A 9F59 7F4D 21A5 6D5F
      # uid                  Swift 2.2 Release Signing Key <[email protected]>
          1BE1E29A084CB305F397D62A9F597F4D21A56D5F \
      # pub   4096R/91D306C6 2016-05-31 [expires: 2018-05-31]
      #       Key fingerprint = A3BA FD35 56A5 9079 C068  94BD 63BC 1CFE 91D3 06C6
      # uid                  Swift 3.x Release Signing Key <[email protected]>
          A3BAFD3556A59079C06894BD63BC1CFE91D306C6 \
        ; do \
          gpg --quiet --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
        done \
    && gpg --batch --verify --quiet swift.tar.gz.sig swift.tar.gz \
    && tar -xzf swift.tar.gz --directory / --strip-components=1 \
    && rm -r "$GNUPGHOME" swift.tar.gz.sig swift.tar.gz \
    && chmod -R o+r /usr/lib/swift

# Post cleanup for binaries orthogonal to swift runtime, but was used to download and install.
RUN apt-get -y remove --purge \
    python2.7

# Post cleanup for binaries orthogonal to swift runtime, but was used to download and install.
RUN apt-get -y remove --purge \
    python2.7

# Print Installed Swift Version
RUN swift --version

Cannot capture context in callback closure

This code

let a = {
   print("got here")
}

Signals.trap(signal: .user(Int(SIGWINCH))) { _ in
   a() 
}

generates this error message:
A C function pointer cannot be formed from a closure that captures context

I hoped that Signals would workaround this issue for me since I got the same message when calling the native signal trapping code i.e.

signal(SIGWINCH, {_ in
   a()
})

maybe it would be nice if this was mentioned in the readme or some documentation on how to get around it.

Could not compile via Carthage.

Probably this project have not shared scheme for carthage.

$ carthage update --platform iOS BlueSignals
*** Cloning BlueSignals
*** Checking out BlueSignals at "1.0.10"
*** xcodebuild output can be found in /var/folders/mj/5zhy3sh11h18pdwrb4v04b300000gn/T/carthage-xcodebuild.kMm90v.log
*** Skipped building BlueSignals due to the error:
Dependency "BlueSignals" has no shared framework schemes for any of the platforms: iOS

If you believe this to be an error, please file an issue with the maintainers at https://github.com/IBM-Swift/BlueSignals/issues/new
$ carthage update BlueSignals
*** Fetching BlueSignals
*** Checking out BlueSignals at "1.0.10"
*** xcodebuild output can be found in /var/folders/mj/5zhy3sh11h18pdwrb4v04b300000gn/T/carthage-xcodebuild.x7e3Go.log
*** Skipped building BlueSignals due to the error:
Dependency "BlueSignals" has no shared framework schemes

If you believe this to be an error, please file an issue with the maintainers at https://github.com/IBM-Swift/BlueSignals/issues/new

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.