1 Reply
      Latest reply on Mar 3, 2020 2:23 AM by eskimo
      liang.zhou Level 1 Level 1 (0 points)

        Hello,

        I'm using kernel control API to send data to a user space daemon from kext.  It works most of the time, but on some occation,  the ctl_enqueuedata() function return the errno code 12(ENOMEM), which is a little weird. This is the snippet in my code.

        // in kext
        errno_t error = ctl_enqueuedata(gCtlInfo.clientCtlRef, gCtlInfo.unit, (void*)notify, sizeof(struct CONFIG_NOTIFY), CTL_DATA_EOR);
        if (0 != error)
        {
            KEXT_LOG_ERROR("Failed to talk to user space daemon(error=%d).", error);
            return result;
        }
        
        // in user space daemon
        dispatch_source_t readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, g_sock, 0, g_globalQueue);
        dispatch_source_set_event_handler_f(readSource, (dispatch_function_t)dataArrived);
        dispatch_resume(readSource);
        
        ssize_t n = recv(sock, (void*)notify, sizeof(struct CONFIG_NOTIFY), 0);
        if (n < sizeof(struct CONFIG_NOTIFY))
        {
            SPDLOG_ERROR("recv() failed, error: {}", strerror(errno));
            return -1;
        }

         

        I just send a fixed-size struct from kext several times per minute, not much data I think. And I also set the buffer large enough in the kern_ctl_reg structure.

        static struct kern_ctl_reg gCtlReg =
        {
            BUNDLE_ID,
            0,
            0,
            0,
            0x800000, //2048KB
            0x800000,
            ctl_connect,
            ctl_disconnect,
            NULL,
            ctl_set,
            NULL 
        };

         

        BTW, my app runs on macOS 10.14.6 with 16GB ram.

        What could be the possible reason for this failure? Thanks!

        • Re: Send data to user space daemon from kext
          eskimo Apple Staff Apple Staff (13,895 points)

          on some occation,  the ctl_enqueuedata function return the errno code 12 (ENOMEM), which is a little weird.

          That’s not that weird.  When you write kernel code you must be careful to not generate unbounded amounts of data.

          The approach I usually use in situations like this is to have the kernel code notify the user space client that data is available and then have the user space client request it.  That means that the kernel code only passes data to the client when it’s actually ready to use it.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"