fork.c 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #define REDISMODULE_EXPERIMENTAL_API
  2. /* define macros for having usleep */
  3. #define _BSD_SOURCE
  4. #define _DEFAULT_SOURCE
  5. #include "redismodule.h"
  6. #include <string.h>
  7. #include <assert.h>
  8. #include <unistd.h>
  9. #define UNUSED(V) ((void) V)
  10. int child_pid = -1;
  11. int exitted_with_code = -1;
  12. void done_handler(int exitcode, int bysignal, void *user_data) {
  13. child_pid = -1;
  14. exitted_with_code = exitcode;
  15. assert(user_data==(void*)0xdeadbeef);
  16. UNUSED(bysignal);
  17. }
  18. int fork_create(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  19. {
  20. long long code_to_exit_with;
  21. if (argc != 2) {
  22. RedisModule_WrongArity(ctx);
  23. return REDISMODULE_OK;
  24. }
  25. RedisModule_StringToLongLong(argv[1], &code_to_exit_with);
  26. exitted_with_code = -1;
  27. child_pid = RedisModule_Fork(done_handler, (void*)0xdeadbeef);
  28. if (child_pid < 0) {
  29. RedisModule_ReplyWithError(ctx, "Fork failed");
  30. return REDISMODULE_OK;
  31. } else if (child_pid > 0) {
  32. /* parent */
  33. RedisModule_ReplyWithLongLong(ctx, child_pid);
  34. return REDISMODULE_OK;
  35. }
  36. /* child */
  37. RedisModule_Log(ctx, "notice", "fork child started");
  38. usleep(500000);
  39. RedisModule_Log(ctx, "notice", "fork child exiting");
  40. RedisModule_ExitFromChild(code_to_exit_with);
  41. /* unreachable */
  42. return 0;
  43. }
  44. int fork_exitcode(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  45. {
  46. UNUSED(argv);
  47. UNUSED(argc);
  48. RedisModule_ReplyWithLongLong(ctx, exitted_with_code);
  49. return REDISMODULE_OK;
  50. }
  51. int fork_kill(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  52. {
  53. UNUSED(argv);
  54. UNUSED(argc);
  55. if (RedisModule_KillForkChild(child_pid) != REDISMODULE_OK)
  56. RedisModule_ReplyWithError(ctx, "KillForkChild failed");
  57. else
  58. RedisModule_ReplyWithLongLong(ctx, 1);
  59. child_pid = -1;
  60. return REDISMODULE_OK;
  61. }
  62. int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  63. UNUSED(argv);
  64. UNUSED(argc);
  65. if (RedisModule_Init(ctx,"fork",1,REDISMODULE_APIVER_1)== REDISMODULE_ERR)
  66. return REDISMODULE_ERR;
  67. if (RedisModule_CreateCommand(ctx,"fork.create", fork_create,"",0,0,0) == REDISMODULE_ERR)
  68. return REDISMODULE_ERR;
  69. if (RedisModule_CreateCommand(ctx,"fork.exitcode", fork_exitcode,"",0,0,0) == REDISMODULE_ERR)
  70. return REDISMODULE_ERR;
  71. if (RedisModule_CreateCommand(ctx,"fork.kill", fork_kill,"",0,0,0) == REDISMODULE_ERR)
  72. return REDISMODULE_ERR;
  73. return REDISMODULE_OK;
  74. }