111-uloop-add-optional-setup-callback-to-process.patch 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. From: Felix Fietkau <[email protected]>
  2. Date: Wed, 8 Oct 2025 22:06:46 +0200
  3. Subject: [PATCH] uloop: add optional setup callback to process()
  4. Add optional setup callback as 5th argument to uloop.process() that is
  5. invoked in the child process after fork() but before exec().
  6. Signed-off-by: Felix Fietkau <[email protected]>
  7. ---
  8. --- a/lib/uloop.c
  9. +++ b/lib/uloop.c
  10. @@ -961,8 +961,9 @@ uc_uloop_process_cb(struct uloop_process
  11. *
  12. * This function creates a process instance for executing external programs.
  13. * It takes the executable path string, an optional string array as the argument
  14. - * vector, an optional dictionary describing environment variables, and a
  15. - * callback function to be invoked when the invoked process ends.
  16. + * vector, an optional dictionary describing environment variables, a
  17. + * callback function to be invoked when the invoked process ends, and an optional
  18. + * setup callback to be invoked in the child process after fork().
  19. *
  20. * @function module:uloop#process
  21. *
  22. @@ -979,6 +980,11 @@ uc_uloop_process_cb(struct uloop_process
  23. * @param {Function} callback
  24. * The callback function to be invoked when the invoked process ends.
  25. *
  26. + * @param {Function} [setup]
  27. + * Optional. A callback function to be invoked in the child process after fork()
  28. + * but before exec(). This can be used to set up file descriptors, change working
  29. + * directory, or perform other initialization.
  30. + *
  31. * @returns {?module:uloop.process}
  32. * Returns a process instance for executing external programs.
  33. * Returns `null` on error, e.g. due to `exec()` failure or invalid arguments.
  34. @@ -988,6 +994,16 @@ uc_uloop_process_cb(struct uloop_process
  35. * const myProcess = uloop.process("/bin/ls", ["-l", "/tmp"], null, (code) => {
  36. * printf(`Process exited with code ${code}\n`);
  37. * });
  38. + *
  39. + * // With setup callback to redirect stderr
  40. + * const myProcess = uloop.process("/bin/ls", ["-l", "/tmp"], null, (code) => {
  41. + * printf(`Process exited with code ${code}\n`);
  42. + * }, () => {
  43. + * const fs = require('fs');
  44. + * const errlog = fs.open('/tmp/error.log', 'w');
  45. + * fs.dup2(errlog.fileno(), 2);
  46. + * errlog.close();
  47. + * });
  48. */
  49. static uc_value_t *
  50. uc_uloop_process(uc_vm_t *vm, size_t nargs)
  51. @@ -996,6 +1012,7 @@ uc_uloop_process(uc_vm_t *vm, size_t nar
  52. uc_value_t *arguments = uc_fn_arg(1);
  53. uc_value_t *env_arg = uc_fn_arg(2);
  54. uc_value_t *callback = uc_fn_arg(3);
  55. + uc_value_t *setup_cb = uc_fn_arg(4);
  56. uc_uloop_process_t *process;
  57. uc_stringbuf_t *buf;
  58. char **argp, **envp;
  59. @@ -1005,7 +1022,8 @@ uc_uloop_process(uc_vm_t *vm, size_t nar
  60. if (ucv_type(executable) != UC_STRING ||
  61. (arguments && ucv_type(arguments) != UC_ARRAY) ||
  62. (env_arg && ucv_type(env_arg) != UC_OBJECT) ||
  63. - !ucv_is_callable(callback)) {
  64. + !ucv_is_callable(callback) ||
  65. + (setup_cb && !ucv_is_callable(setup_cb))) {
  66. err_return(EINVAL);
  67. }
  68. @@ -1015,6 +1033,13 @@ uc_uloop_process(uc_vm_t *vm, size_t nar
  69. err_return(errno);
  70. if (pid == 0) {
  71. + if (setup_cb) {
  72. + uc_vm_stack_push(vm, ucv_get(setup_cb));
  73. +
  74. + if (uc_uloop_vm_call(vm, false, 0))
  75. + ucv_put(uc_vm_stack_pop(vm));
  76. + }
  77. +
  78. argp = calloc(ucv_array_length(arguments) + 2, sizeof(char *));
  79. envp = environ;